library(tidyverse)
# library(MouseGastrulationData)
library(SingleCellExperiment)
library(scater)
library(scran)
library(bit64)
Loading required package: bit

Attaching package: 'bit'

The following object is masked from 'package:base':

    xor

Attaching package bit64
package:bit64 (c) 2011-2017 Jens Oehlschlaegel
creators: integer64 runif64 seq :
coercion: as.integer64 as.vector as.logical as.integer as.double as.character as.bitstring
logical operator: ! & | xor != == < <= >= >
arithmetic operator: + - * / %/% %% ^
math: sign abs sqrt log log2 log10
math: floor ceiling trunc round
querying: is.integer64 is.vector [is.atomic} [length] format print str
values: is.na is.nan is.finite is.infinite
aggregation: any all min max range sum prod
cumulation: diff cummin cummax cumsum cumprod
access: length<- [ [<- [[ [[<-
combine: c rep cbind rbind as.data.frame
WARNING don't use as subscripts
WARNING semantics differ from integer
for more help type ?bit64

Attaching package: 'bit64'

The following objects are masked from 'package:SummarizedExperiment':

    match, order, rank

The following object is masked from 'package:Biobase':

    cache

The following objects are masked from 'package:GenomicRanges':

    match, order, rank

The following objects are masked from 'package:IRanges':

    match, order

The following objects are masked from 'package:S4Vectors':

    %in%, match, order, rank

The following objects are masked from 'package:BiocGenerics':

    %in%, match, order, rank

The following objects are masked from 'package:base':

    :, %in%, is.double, match, order, rank
library(patchwork)
library(ggpubr)

source('~/milo/notebooks/benchmark/benchmark_utils.R')
figdir <- "~/mount/gdrive/milo/Figures/benchmark_v2/"
if (!dir.exists(figdir)) {
  dir.create(figdir)  
}

Some plotting utils

## color palette for methods
method_names <- c("milo", "daseq", "meld", "louvain", "cydar")
method_colors <- RColorBrewer::brewer.pal(7, name="Dark2")[c(1:4,6)]
method_colors <- setNames(method_colors, method_names)
method_labels <- c("Milo", "DAseq", "MELD", "Louvain", "cydar")
method_labels <- setNames(method_labels, method_names)

scale_color_methods <- function(){ scale_color_manual(values = method_colors, labels=method_labels) }
scale_fill_methods <- function(){ scale_fill_manual(values = method_colors, labels=method_labels) }

remove_x_axis <- function(){
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.x = element_blank())  
}

remove_y_axis <- function(){
  theme(axis.text.y = element_blank(), axis.ticks.y = element_blank(), axis.title.y = element_blank())  
}
enr_labeller2 <- function(value){
  fc <- round(prob2FC(as.numeric(value)), 2)
  enr_name <- paste("logFC = ", fc)
  return(c(value=enr_name))
}

pl_labeller <- labeller(method=as_labeller(setNames(method_labels, method_names)),
     enr=enr_labeller2)

In this notebook I will visualize the results from benchmarking Milo against 4 alternative DA analysis methods.

Benchmarking workflow

All the main functions are implemented in benchmark/benchmark_utils.R. These functions are wrapped in several scripts:

Define input datasets

These are going to be used as underlying KNN graphs with different topologies for benchmarking.

Simulated datasets

Provided by Mike, constructed with dyntoy

Prepare datasets (uniform naming of dim reduction and celltype column)

branch_sce_3x <- readRDS("~/mount/gdrive/milo/BranchingSimulation-3X.RDS")
branch_sce_3x$cell <- colnames(branch_sce_3x)
branch_sce_3x$celltype <- branch_sce_3x$group_id
names(reducedDims(branch_sce_3x)) <- c("pca.corrected", "UMAP")
saveRDS(branch_sce_3x, "/nfs/team205/ed6/data/milo_benchmark/branching3x_data_bm.RDS")

linear_sce_3x <- readRDS("~/mount/gdrive/milo/LinearTrajSyntheticLabels-3X.RDS")
linear_sce_3x$cell <- colnames(linear_sce_3x)
linear_sce_3x$celltype <- linear_sce_3x$group_id
names(reducedDims(linear_sce_3x)) <- c("pca.corrected", "UMAP")
saveRDS(linear_sce_3x, "/nfs/team205/ed6/data/milo_benchmark/linear3x_data_bm.RDS")

cluster_sce_3x <- readRDS("~/mount/gdrive/milo/DiscreteSyntheticLabels-3X.RDS")
cluster_sce_3x$cell <- colnames(cluster_sce_3x)
cluster_sce_3x$celltype <- cluster_sce_3x$Block
names(reducedDims(cluster_sce_3x)) <- c("pca.corrected", "UMAP")
saveRDS(cluster_sce_3x, "/nfs/team205/ed6/data/milo_benchmark/cluster3x_data_bm.RDS")

Mouse gastrulation data

Select samples from late time points (even number of replicates)

AtlasSampleMetadata %>%
  arrange(stage) %>%
  mutate(sample=factor(sample, levels=unique(sample))) %>%
  ggplot(aes(stage, sample)) +
  geom_point()

late_samples <- AtlasSampleMetadata %>%
  filter(stage %in% c("E7.75", "E8.0", "E8.25", "E8.5")) %>%
  pull(sample)
embryo_sce <- EmbryoAtlasData(type="processed", samples = late_samples)
data.frame(colData(embryo_sce)) %>%
  ggplot(aes(as.factor(sample), as.factor(pool))) + geom_point()
embryo_sce

Preprocessing

logcounts(embryo_sce) <- log1p(counts(embryo_sce))
## Exclude zero counts genes
keep.rows <- rowSums(logcounts(embryo_sce)) != 0
embryo_sce <- embryo_sce[keep.rows, ]

dec <- modelGeneVar(embryo_sce)
hvgs <- getTopHVGs(dec, n=5000)

## Drop cells with NAs in corrected pca (low quality)
embryo_sce <- embryo_sce[,apply(reducedDim(embryo_sce, "pca.corrected"), 1, function(x) all(!is.na(x)))]

## Run UMAP (the data has been subsetted)
# embryo_sce <- scater::runPCA(embryo_sce, subset_row=hvgs)
embryo_sce <- scater::runUMAP(embryo_sce, dimred="pca.corrected")
plotReducedDim(embryo_sce, "UMAP", colour_by="celltype", text_by="celltype", point_size=0.1) +
  scale_color_manual(values=EmbryoCelltypeColours) +
  guides(color=guide_legend(override.aes = list(size=2)))

Save object 4 benchmark

saveRDS(embryo_sce, "/nfs/team205/ed6/data/milo_benchmark/embryo_data_bm.RDS")
embryo_sce <- readRDS("/nfs/team205/ed6/data/milo_benchmark/embryo_data_bm.RDS")

Save list of celltype names and sample by sizes

for (i in 1:3) {
  pop_size_df <- as.data.frame(table(embryo_sce$celltype)) %>%
  rename(pop=Var1, pop_size=Freq) %>%
  mutate(size_bin = cut(pop_size, breaks = 10)) %>%
  group_by(size_bin) %>%
  sample_n(size=1) 
  write(as.character(pop_size_df$pop), glue("/nfs/team205/ed6/data/milo_benchmark/pop_sample_{i}.txt"))
}

Sanity check of synthetic labels on embryo data

pops <- scan("/nfs/team205/ed6/data/milo_benchmark/pop_sample_2_clean.txt", what="")
umap_ls <- lapply(pops, function(p){
  filename <- paste0('/nfs/team205/ed6/data/milo_benchmark/synthetic_data/benchmark_embryo_pop_',
                             str_replace(p, " ", "_"),
                             '_enr0.8_seed45.coldata.csv')
  if (file.exists(filename)){
    coldata <- read_csv(filename)
    colData(embryo_sce) <- column_to_rownames(coldata) %>% DataFrame()
    data.frame(reducedDim(embryo_sce, 'UMAP')) %>%
      dplyr::rename(UMAP1=X1, UMAP2=X2) %>%
      mutate(Condition1_prob=embryo_sce$Condition1_prob > 0.6) %>%
      ggplot(aes(UMAP1, UMAP2, color=Condition1_prob)) +
      ggrastr::geom_point_rast(size=0.1, dpi=700) +
      scale_color_viridis_d() +
      theme_classic(base_size = 16)  
  }
    })

umap_ls
pops <- scan("/nfs/team205/ed6/data/milo_benchmark/pop_sample_2_clean.txt", what="")
umap_ls <- lapply(pops, function(p){
  filename <- paste0('/nfs/team205/ed6/data/milo_benchmark/synthetic_data/benchmark_embryo_pop_',
                             str_replace(p, " ", "_"),
                             '_enr0.9_seed45.coldata.csv')
  if (file.exists(filename)){
    coldata <- read_csv(filename)
    colData(embryo_sce) <- column_to_rownames(coldata) %>% DataFrame()
    data.frame(reducedDim(embryo_sce, 'UMAP')) %>%
      dplyr::rename(UMAP1=X1, UMAP2=X2) %>%
      mutate(Condition1_prob=embryo_sce$Condition1_prob > 0.6) %>%
      ggplot(aes(UMAP1, UMAP2, color=Condition1_prob)) +
      ggrastr::geom_point_rast(size=0.1, dpi=700) +
      scale_color_viridis_d() +
      theme_classic(base_size = 16)  
  }
    })

umap_ls

Pick threshold for cells in true DA regions based on p(C1) distribution

Read full outcomes and true probabilities

read4_prob_hist <- function(data_id){
  outdir <- glue("/nfs/team205/ed6/data/milo_benchmark/{data_id}/")
  res_files <- list.files(outdir, pattern=glue("{data_id}.+batchEffect0.DAresults"))
  res_files_full <- list.files(outdir, pattern=glue("{data_id}.+batchEffect0.DAresults"), full.names = TRUE)
  res_files_full_nomeld <- str_subset(res_files_full, "meld|cydar_batch|louvain_batch|milo_batch", negate = TRUE)
  
  res_ls <- lapply(seq_along(res_files_full_nomeld), function(i){ 
    print(paste("Outcome no. ", i))
    benchmark_df <- read_csv(res_files_full_nomeld[i]) 
    ## Check if conditions were swapped in test
    pred_cor <- benchmark_df %>%
      mutate(pred=factor(pred, levels=c("NegLFC", "NotDA", "PosLFC"), ordered = TRUE)) %>%
      mutate(pred=as.numeric(pred)) %>%
      summarise(cor(pred, true_prob))
    ## Swap outcomes if so
    if (!is.na(pred_cor)) {
      if (pred_cor < - 0.1) {
        benchmark_df <- mutate(benchmark_df, pred = ifelse(pred=="NegLFC", "PosLFC", ifelse(pred=="PosLFC", "NegLFC", "NotDA")))
      }
    }
    benchmark_df %>%
      mutate(id=i)
    })
  
  res_df <- res_ls  %>%
    purrr::reduce(bind_rows) 
  # %>%
  #   select(true_prob, pred, method) 
  
  return(res_df)  
}

cluster_res_df <- read4_prob_hist("cluster3x")
linear_res_df <- read4_prob_hist("linear3x")
branch_res_df <- read4_prob_hist("branching3x")
embryo_res_df <- read4_prob_hist("embryo")

Plot distribution of P(C1) in cells identified as DA by different methods

Use 75% quantile of P(C1) in all cells to define threshold for true DA

linear_thresh <- calculate_quantile_thresh(linear_res_df)
Warning messages:
1: In readChar(file, size, TRUE) : truncating string with embedded nuls
2: In readChar(file, size, TRUE) : truncating string with embedded nuls
branching_thresh <- calculate_quantile_thresh(branch_res_df)
embryo_thresh <- calculate_quantile_thresh(embryo_res_df)

Benchmarking on simulated data

Define utils

data.frame(reducedDim(sce, red_dim))
Error in h(simpleError(msg, call)) : 
  error in evaluating the argument 'type' in selecting a method for function 'reducedDim': object 'red_dim' not found

Linear - 1D trajectory

outdir <- "/nfs/team205/ed6/data/milo_benchmark/linear3x/"
res_files <- list.files(outdir, pattern="linear.+DAresults")
res_files_full <- list.files(outdir, pattern="linear3x.+DAresults", full.names = TRUE)
in_files <- list.files("~/data/milo_benchmark/synthetic_data/", pattern="linear3x.+coldata.csv")

## Make data frame w benchmark parameters
linear_out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed", "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove(batchEffect, "batchEffect")) 

## Load results
linear_outcome_df <- lapply(seq_along(res_files_full), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[i]) %>%
      .outcome_by_prob(da_upper = linear_thresh) %>%
      mutate(DA_thresh=linear_thresh) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(linear_out_meta_df[i,]) 
  pop_enr <- as.numeric(linear_out_meta_df[i,"enr"])
  benchmark_df
  }) %>%
  purrr::reduce(bind_rows) %>%
  ## Remove MELD
  filter(method!="meld")

linear_outcome_df 
pl_df <- linear_outcome_df %>%
  filter(method!="milo_batch") %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(pop=str_replace(pop, "_", " ")) %>%
  mutate(pop=factor(pop, levels=unique(pop))) %>%
  filter(DA_thresh >= linear_thresh & batchEffect==0) 
pl_right <- pl_df %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), TPR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
    theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())
pl_left <- pl_df %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), FDR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
    theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())

pl <- pl_right / pl_left +
  plot_layout(guides='collect') &
    theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())

pl

Plot UMAP

linear_sce <- readRDS("~/data/milo_benchmark/linear3x_data_bm.RDS")
indir <- "~/data/milo_benchmark/synthetic_data/"

names(reducedDims(linear_sce))[2] <- "umap_batch"
colnames(reducedDims(linear_sce)[[2]]) <- c("X1", "X2") 

pl_top <- plot_outcome_umap(linear_sce, method = 'milo', pop="M5", enr = 0.9, seed = 43,batchEffect = 0, true = TRUE, data_id="linear3x") +
  theme(legend.position="top") 

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  group_id = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)
plot_linear <- ((pl_top) | (pl & theme(legend.position="top"))) +
  plot_layout(widths = c(0.5,2))
plot_linear

Branching

outdir <- "/nfs/team205/ed6/data/milo_benchmark/branching3x/"
res_files <- list.files(outdir, pattern="branching3x.+DAresults")
res_files_full <- list.files(outdir, pattern="branching3x.+DAresults", full.names = TRUE)
in_files <- list.files("~/data/milo_benchmark/synthetic_data/", pattern="branching3x.+coldata.csv")

## Make data frame w benchmark parameters
branch_out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed", "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove(batchEffect, "batchEffect")) 

## Load results
branch_outcome_df <- lapply(seq_along(res_files_full), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[i]) %>%
      .outcome_by_prob(da_upper = branching_thresh) %>%
      mutate(DA_thresh=branching_thresh) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(branch_out_meta_df[i,]) 
  pop_enr <- as.numeric(branch_out_meta_df[i,"enr"])
  benchmark_df
  }) %>%
  purrr::reduce(bind_rows) %>%
  ## Remove MELD
  filter(method!="meld")

branch_outcome_df 
  
pl_df <- branch_outcome_df %>%
  filter(method!="milo_batch") %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(pop=str_replace(pop, "_", " ")) %>%
  mutate(pop=factor(pop, levels=unique(pop))) %>%
  filter(DA_thresh >= branching_thresh & batchEffect==0) 
pl_right <- pl_df %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), TPR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
    theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())
pl_left <- pl_df %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), FDR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
  theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())

pl <- pl_right / pl_left +
plot_layout(guides='collect') &
    theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())
pl

Plot UMAP

branch_sce <- readRDS("~/data/milo_benchmark/branching3x_data_bm.RDS")
indir <- "~/data/milo_benchmark/synthetic_data/"

names(reducedDims(branch_sce))[2] <- "umap_batch"
colnames(reducedDims(branch_sce)[[2]]) <- c("X1", "X2") 

pl_top <- plot_outcome_umap(branch_sce, method = 'milo', pop="M5", enr = 0.9, seed = 43,batchEffect = 0, true = TRUE, data_id="branching3x") +
  theme(legend.position="top") 

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  group_id = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)
plot_branch <- ((pl_top) | (pl & theme(legend.position="top"))) +
  plot_layout(widths = c(0.5,2))
plot_branch

Simple clustering

outdir <- "/nfs/team205/ed6/data/milo_benchmark/cluster3x/"
res_files <- list.files(outdir, pattern="cluster3x.+DAresults")
res_files_full <- list.files(outdir, pattern="cluster3x.+DAresults", full.names = TRUE)
in_files <- list.files("~/data/milo_benchmark/synthetic_data/", pattern="cluster3x.+coldata.csv")

## Make data frame w benchmark parameters
cluster_out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed", "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove(batchEffect, "batchEffect")) 

## Load results
cluster_outcome_df <- lapply(seq_along(res_files_full), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[i]) %>%
      .outcome_by_prob(da_upper = 0.55) %>%
      mutate(DA_thresh=0.55) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(cluster_out_meta_df[i,]) 
  pop_enr <- as.numeric(cluster_out_meta_df[i,"enr"])
  benchmark_df
  }) %>%
  purrr::reduce(bind_rows) %>%
  ## Remove MELD
  filter(method!="meld")
[1] "Outcome no.  1"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  2"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  3"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  4"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  5"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  6"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  7"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  8"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  9"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  10"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  11"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  12"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  13"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  14"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  15"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  16"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  17"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  18"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  19"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  20"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  21"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  22"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  23"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  24"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  25"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  26"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  27"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  28"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  29"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  30"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  31"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  32"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  33"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  34"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  35"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  36"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  37"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  38"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  39"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  40"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  41"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  42"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  43"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  44"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  45"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  46"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  47"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  48"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  49"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  50"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  51"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  52"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  53"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  54"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  55"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  56"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  57"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  58"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  59"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  60"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  61"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  62"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  63"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  64"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  65"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  66"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  67"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  68"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  69"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  70"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  71"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  72"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  73"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  74"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  75"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  76"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  77"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  78"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  79"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  80"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  81"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  82"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  83"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  84"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  85"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  86"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  87"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  88"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  89"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  90"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  91"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  92"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  93"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  94"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  95"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  96"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  97"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  98"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  99"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  100"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  101"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  102"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  103"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  104"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  105"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  106"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  107"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  108"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  109"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  110"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  111"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  112"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  113"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  114"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  115"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  116"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  117"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  118"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  119"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  120"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  121"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  122"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  123"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  124"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  125"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  126"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  127"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  128"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  129"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  130"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  131"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  132"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  133"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  134"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  135"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  136"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  137"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  138"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  139"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  140"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  141"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  142"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  143"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  144"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  145"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  146"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  147"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  148"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  149"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  150"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  151"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  152"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  153"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  154"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  155"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  156"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  157"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  158"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  159"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  160"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  161"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  162"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  163"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  164"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  165"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  166"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  167"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  168"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  169"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  170"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  171"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  172"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  173"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  174"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  175"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  176"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  177"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  178"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  179"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  180"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  181"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  182"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  183"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  184"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  185"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  186"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  187"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  188"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  189"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  190"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  191"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  192"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  193"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  194"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  195"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  196"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  197"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  198"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  199"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  200"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  201"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  202"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  203"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  204"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  205"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  206"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  207"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  208"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  209"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  210"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  211"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  212"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  213"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  214"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  215"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  216"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  217"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  218"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  219"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  220"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  221"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  222"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  223"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  224"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  225"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  226"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  227"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  228"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  229"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  230"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Condition2 = col_double(),
  method = col_character(),
  true = col_character(),
  true_prob = col_double()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  231"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  232"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  233"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  234"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  235"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  236"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  237"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  238"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  239"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  240"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  241"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  242"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  243"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
cluster_outcome_df 
NA
pl_df <- cluster_outcome_df %>%
 filter(method!="milo_batch") %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(pop=str_replace(pop, "_", " ")) %>%
  mutate(pop=factor(pop, levels=unique(pop))) %>%
  filter(DA_thresh >= 0.55 & batchEffect==0) 
pl_right <- pl_df %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), TPR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
  theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
    axis.title.x = element_blank())
pl_left <- pl_df %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), FDR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
  theme(#axis.text.x = element_blank(), axis.ticks.x = element_blank(), 
        axis.title.x = element_blank()
        )

pl <- pl_right / pl_left +
plot_layout(guides='collect') &
  theme(#axis.text.x=element_blank(), axis.ticks.x=element_blank(), 
        axis.title.x=element_blank()
        )
pl

Plot UMAP

cluster_sce <- readRDS("~/data/milo_benchmark/cluster3x_data_bm.RDS")
indir <- "~/data/milo_benchmark/synthetic_data/"

names(reducedDims(cluster_sce))[2] <- "umap_batch"
colnames(reducedDims(cluster_sce)[[2]]) <- c("X1", "X2") 
pl_top <- plot_outcome_umap(cluster_sce, method = 'milo', pop="B3", enr = 0.9, seed = 43,batchEffect = 0, true = TRUE, data_id="cluster3x") + 
 theme(legend.position="top") 

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Block = col_character(),
  Replicate = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)
plot_cluster <- ((pl_top) | (pl & theme(legend.position="top"))) +
  plot_layout(widths = c(0.5,2))
plot_cluster

Assemble figure

fig <- (
   (plot_cluster ) /
   (plot_linear & theme(legend.position="none")) /
   (plot_branch & theme(legend.position="none"))
   ) + 
  plot_layout() &
  theme(strip.text = element_text(size=11))

fig +
  ggsave(paste0(figdir, "simData_figure.png"), width=10, height = 13) +
  ggsave(paste0(figdir, "simData_figure.pdf"), width=10, height = 13)

Check some examples

plot_outcome_umap(sce = linear_sce, method="louvain", pop="B3", enr=0.9, seed=43, batchEffect = '0', data_id = "cluster3x", true=FALSE) +
plot_outcome_umap(sce = linear_sce, method="cydar",   pop="B3", enr=0.9, seed=43, batchEffect = '0', data_id = "cluster3x", true=FALSE) +
plot_outcome_umap(sce = linear_sce, method="milo",    pop="B3", enr=0.9, seed=43, batchEffect = '0', data_id = "cluster3x", true=FALSE) +
plot_outcome_umap(sce = linear_sce, method="daseq",   pop="B3", enr=0.9, seed=43, batchEffect = '0', data_id = "cluster3x", true=FALSE) +
plot_outcome_umap(sce = linear_sce, method="daseq", pop="B3", enr=0.9, seed=43, batchEffect = '0', data_id = "cluster3x", true=TRUE) +
  plot_layout(guides="collect")

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Block = col_character(),
  Replicate = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

'-' not meaningful for factors
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Block = col_character(),
  Replicate = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

'-' not meaningful for factors
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Block = col_character(),
  Replicate = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

'-' not meaningful for factors
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Block = col_character(),
  Replicate = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

'-' not meaningful for factors
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  rowname = col_character(),
  Block = col_character(),
  Replicate = col_character(),
  cell = col_character(),
  celltype = col_character(),
  synth_labels = col_character(),
  synth_samples = col_character(),
  synth_batches = col_character(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double(),
  true_labels = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

MELD / Milo comparison

Comparing accuracy and precision of the fold-change estimates of the two methods running MELD and Milo on the same simulation on the embryo data.

We estimate LFCs for both methods (see run_miloVSmeld.R) and compare with the true LFC

pl_labeller <- labeller(
  enr = enr_labeller2,
  true_labels = label_value,
  pop = label_value,
  .default = label_both
)
Error in labeller(enr = enr_labeller2, true_labels = label_value, pop = label_value,  : 
  object 'enr_labeller2' not found

pl_milo <- lfc_df %>% 
  filter(pop %in% c("Gut", "Erythroid1", "Somitic_mesoderm")) %>%
  filter(method=="milo_LFC" & batchEffect=='0.5') %>%
  group_by(enr, true_labels, pop, k) %>%
  mutate(MAE = MAE(true_LFC, estimated_LFC)) %>%
  ggplot(aes(true_LFC, estimated_LFC)) + 
  geom_point(size=0.6, aes(color=true_labels)) +
  geom_hline(yintercept = 0, linetype=2) +
  geom_vline(xintercept = 0, linetype=2) +
  geom_abline(linetype=2) +
  scale_color_manual(values=c(NegLFC="red", NotDA="grey"), labels=c(NegLFC="NegLFC", NotDA="no DA"), name='') +
  guides(color=guide_legend(override.aes = c(size=2))) +
  facet_grid(pop~enr, labeller = pl_labeller) +
  xlab("True LFC") + ylab("Milo estimated LFC") +
  theme_bw(base_size = 14)

pl_meld <- lfc_df %>% 
  filter(pop %in% c("Gut", "Erythroid1", "Somitic_mesoderm")) %>%
  filter(method=="meld_LFC" & batchEffect=='0.5') %>%
  # filter(enr==0.9 & k==50 & true_labels=="NegLFC")
  group_by(enr, true_labels, pop, k) %>%
  mutate(MAE = MAE(true_LFC, estimated_LFC)) %>%
  ggplot(aes(true_LFC, estimated_LFC)) + 
  geom_point(size=0.6, aes(color=true_labels)) +
  geom_hline(yintercept = 0, linetype=2) +
  geom_vline(xintercept = 0, linetype=2) +
  geom_abline(linetype=2) +
  xlab("True LFC") + ylab("MELD estimated LFC") +
  guides(color=guide_legend(override.aes = c(size=2))) +
  scale_color_manual(values=c(NegLFC="red", NotDA="grey"), labels=c(NegLFC="NegLFC", NotDA="no DA"), name="") +
  facet_grid(pop~enr, labeller = pl_labeller) +
  theme_bw(base_size = 14)


pl_left_be <- (pl_milo | pl_meld) + 
  plot_layout(guides="collect") &
  theme(legend.position="top", legend.justification = c(1,1))
pl_right1 <- lfc_df %>%
  filter(k==50) %>%
  group_by(method, pop, true_labels, k, enr, batchEffect) %>%
  summarise(MSE = MSE(true_LFC, estimated_LFC), sd=sd(abs(true_LFC - estimated_LFC))) %>%
  ungroup() %>%
  mutate(method = str_remove(method,"_LFC")) %>%
  dplyr::rename(`Batch effect \nmagnitude` = batchEffect) %>%
  filter(true_labels=="NotDA") %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)), 1)), MSE, color = method)) +
  geom_boxplot() +
  facet_grid(true_labels~`Batch effect \nmagnitude`, labeller=pl_labeller) +
  theme_bw(base_size=18) +
  xlab("Simulated log-Fold Change") +
  scale_color_methods() +
  theme(legend.position="top", legend.justification = c(1,1)) +
  ylim(0,0.6)
`summarise()` has grouped output by 'method', 'pop', 'true_labels', 'k', 'enr'. You can override using the `.groups` argument.
pl_right2 <- lfc_df %>%
  filter(k==50) %>%
  group_by(method, pop, true_labels, k, enr, batchEffect) %>%
  summarise(MSE = MSE(true_LFC, estimated_LFC), sd=sd(abs(true_LFC - estimated_LFC))) %>%
  ungroup() %>%
  mutate(method = str_remove(method,"_LFC")) %>%
  dplyr::rename(`Batch effect \nmagnitude` = batchEffect) %>%
  filter(true_labels=="NegLFC") %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)), 1)), MSE, color = method)) +
  geom_boxplot() +
  facet_grid(true_labels~`Batch effect \nmagnitude`, labeller=pl_labeller) +
  theme_bw(base_size=18) +
  xlab("Simulated log-Fold Change") +
  scale_color_methods() +
  theme(legend.position="top", legend.justification = c(1,1)) +
  ylim(0,0.6)
`summarise()` has grouped output by 'method', 'pop', 'true_labels', 'k', 'enr'. You can override using the `.groups` argument.
pl_right <- pl_right1 + pl_right2 +
  plot_layout(guides="collect") &
  theme(legend.position="top", legend.justification = c(1,1)) 

pl_right

Embryo data

W/o batch effect

## Read outputs
outdir <- "/nfs/team205/ed6/data/milo_benchmark/embryo/"
res_files <- list.files(outdir, pattern=".DAresults")
res_files_full <- list.files(outdir, pattern=".DAresults", full.names = TRUE)
# in_files <- list.files("~/data/milo_benchmark/synthetic_data/", pattern="coldata.csv")

## Make data frame w benchmark parameters
out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed", "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove_all(batchEffect, "batchEffect")) 

## Read benchmark results w/o batch effects
no_batch_files <- str_detect(res_files_full, "batchEffect0.DAresult") & !str_detect(res_files_full, "louvain_batch|cydar_batch|milo_batch")
# prob_thresh_vec <- seq(0.5, 0.9, 0.05)
outcome_df <- lapply(seq_along(res_files_full[no_batch_files]), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[no_batch_files][i])
  pop_enr <- as.numeric(out_meta_df[no_batch_files,][i,"enr"])
  benchmark_df %>%
      .outcome_by_prob(da_upper = embryo_thresh) %>%
      mutate(DA_thresh=embryo_thresh) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(out_meta_df[no_batch_files,][i,]) %>%
      filter(DA_thresh < as.numeric(enr))
}) %>%
  purrr::reduce(bind_rows)

write_csv(outcome_df, "/nfs/team205/ed6/data/milo_benchmark/outcome_embryo_v3_noBatch.csv")

Read outcome for embryo (built with wrapper build_outcome.R)

outcome_df <- read_csv("/nfs/team205/ed6/data/milo_benchmark/outcome_embryo_v3_noBatch.csv")

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  FN = col_double(),
  TN = col_double(),
  TP = col_double(),
  FP = col_double(),
  TPR = col_double(),
  FPR = col_double(),
  TNR = col_double(),
  FNR = col_double(),
  FDR = col_double(),
  Precision = col_double(),
  Power = col_double(),
  Accuracy = col_double(),
  DA_thresh = col_double(),
  pop = col_character(),
  enr = col_double(),
  seed = col_double(),
  batchEffect = col_double(),
  method = col_character()
)
outcome_df <- outcome_df %>%
  filter(DA_thresh==embryo_thresh) %>%
  filter(pop!="Mixed_mesoderm")
# enr_labeller2 <- function(variable, value, split_lines=FALSE){
#   fc <- round(prob2FC(as.numeric(value)), 2)
#   enr_name <- paste("logFC = ", fc)
#   return(enr_name)
# }

pl_df <- outcome_df %>% 
   filter(batchEffect==0 & str_detect(method, "_batch", negate = TRUE)) %>% 
   mutate(FDR = FP/(TP+FP)) %>% 
   mutate(TPR=ifelse(is.nan(TPR), 0, TPR), 
          FPR=ifelse(is.nan(FPR), 0, FPR), 
          FDR=ifelse(is.nan(FDR), 0, FDR), 
          Precision=ifelse(is.nan(Precision), 0, Precision)) %>% 
   filter(DA_thresh >= embryo_thresh & batchEffect==0)  %>% 
   mutate(enr=as.character(enr))  

p_top <- pl_df %>%
  filter(batchEffect=="0") %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), TPR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  # geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.x = element_blank())

p_bottom <- pl_df %>%
  filter(batchEffect=="0") %>%
  ggplot(aes(as.factor(round(prob2FC(as.numeric(enr)),1)), FDR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=pl_labeller) +
  xlab('Simulated log-Fold Change') 

(p_top / p_bottom) + plot_layout(guides="collect") +
  ggsave("~/mount/gdrive/milo/Figures/benchmark_v2/bm_nobatch.pdf",  width = 11, height = 6) +
  ggsave("~/mount/gdrive/milo/Figures/benchmark_v2/bm_nobatch.png",  width = 11, height = 6)

Impact of population size

Range of sizes

mutate(outcome_df, nDA= TP+FN) %>%
  filter(method=="milo" & batchEffect=="0") %>%
  summarise(min(nDA))
  ggplot(aes(nDA,TPR)) +
  geom_point()

Generate labels

  • Changing logit param: to have bigger DA region around the same centroid
  • capping the enrichment, so to have the same number of DA cells with different fold changes

I pick Erythroid2 and Caudal_neurectoderm as the best and worse performance regions

save_labels_capped <- function(sce, cap_enr, pop, seed, a_logit){
  if (str_detect(pop, "_")) {
    pop <- str_replace(pop, "_", " ")
  }
  sce <- add_synthetic_labels_pop(sce, pop=pop, pop_column = "celltype", seed=seed, pop_enr=0.9, cap_enr = cap_enr,a_logit =  a_logit)
  true_labels <- ifelse(sce$Condition1_prob < (1-cap_enr), "NegLFC", ifelse(sce$Condition2_prob > cap_enr, "PosLFC", "NotDA"))
  colData(sce)[["true_labels"]] <- true_labels
  if (str_detect(pop, " ")) {
    pop <- str_replace(pop, " ", "_")
  }
  
  ## Save coldata
  outdir <-'/nfs/team205/ed6/data/milo_benchmark/synthetic_data/'
  a <- str_remove(as.character(a_logit), "\\.")
  outprefix <- str_c("benchmark_embryo_pop_", pop, '_enr', cap_enr, "_seed", seed, "_capped_logit", a)
  coldata <- data.frame(colData(sce)) %>% rownames_to_column()
  write_csv(coldata, str_c(outdir, outprefix, ".coldata.csv"))
  }


sce <- embryo_sce
## Exclude mixed mesoderm (it's too mixed)
pops <- c("Erythroid2", "Caudal_neurectoderm")

for (p in pops) {
  for (e in seq(0.75,0.95, by=0.1) ) {
    for (s in c(43,44,45) ) {
      for (a in c(0.3,0.5, 0.7) ) {
      save_labels_capped(embryo_sce, e, p, s, a)
      }
    }
  }
}

I run the benchmark with synthetic labels generated above (see submit_benchmark_capped.sh)

Read all results

outdir <- "/nfs/team205/ed6/data/milo_benchmark/capped_logit/"
res_files <- list.files(outdir, pattern=".+DAresults.+.csv")
res_files_full <- list.files(outdir, pattern=".+DAresults.+.csv", full.names = TRUE)
# in_files <- list.files("~/data/milo_benchmark/synthetic_data/", pattern="_enr0.[78].+coldata.csv")

## Make data frame w benchmark parameters
capped_out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed",'capped','logit', "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove(batchEffect, "batchEffect"),
         logit=str_remove(logit, "logit")) 

## Load results
capped_outcome_df <- lapply(seq_along(res_files_full), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[i]) %>%
      .outcome_by_prob(da_upper = embryo_thresh) %>%
      mutate(DA_thresh=embryo_thresh) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(capped_out_meta_df[i,]) 
  pop_enr <- as.numeric(capped_out_meta_df[i,"enr"])
  benchmark_df
  }) %>%
  purrr::reduce(bind_rows)

outcome_df_popsize <- capped_outcome_df
## Merge with benchmark outcomes
pl_df <- outcome_df_popsize %>%
  filter(str_detect(method, "_batch", negate = TRUE)) %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  # mutate(pop=str_replace(pop, "_", " ")) %>%
  left_join(DA_pop_size_df) %>%
  arrange(pop_size) %>%
  mutate(pop=factor(pop, levels=unique(pop))) %>%
  mutate(enr=as.character(enr))
Joining, by = c("pop", "enr", "seed", "logit")

Explain variability in performance across different populations

Due to low signal to noise ratio for certain simulations

## Read benchmark results w/o batch effects and selecting just top and bottom population
keep_pops <- c("Erythroid2", "Caudal_neurectoderm")
keep_files <- str_detect(res_files_full, "batchEffect0.DAresult") & 
  !str_detect(res_files_full, "louvain_batch|cydar_batch|milo_batch") &
  str_detect(res_files_full, paste0(keep_pops, collapse = "|"))

suppressWarnings({
  outcome_df_2 <- lapply(seq_along(res_files_full[keep_files]), function(i){ 
    print(paste("Outcome no. ", i))
    benchmark_df <- read_csv(res_files_full[keep_files][i])
    pop_enr <- as.numeric(out_meta_df[keep_files,][i,"enr"])
    benchmark_df <- benchmark_df %>%
      mutate(true = ifelse(benchmark_df$true_prob < 1-embryo_thresh, "NegLFC", ifelse(benchmark_df$true_prob > embryo_thresh, "PosLFC", "NotDA"))) 
    
    ## Check if conditions were swapped in test
    pred_cor <- benchmark_df %>%
      group_by(pred) %>%
      summarise(m=mean(true_prob)) %>%
      ungroup() %>%
      mutate(pred=factor(pred, levels=c("NegLFC", "NotDA", "PosLFC"), ordered = TRUE)) %>%
      mutate(pred=as.numeric(pred)) %>%
      summarise(c=cor(pred, m)) %>%
      pull(c)
    ## Swap outcomes if so
    if (!is.na(pred_cor)) {
      if (pred_cor < 0) {
        benchmark_df <- mutate(benchmark_df, pred = ifelse(pred=="NegLFC", "PosLFC", ifelse(pred=="PosLFC", "NegLFC", "NotDA")))
      }
    }
   
    benchmark_df %>%
      mutate(prob_bins=cut(1-true_prob, breaks = seq(0.3, 1, by=0.05), include.lowest = TRUE, right=FALSE)) %>%
        group_by(prob_bins) %>%
        do(calculate_outcome(.)) %>%
        ungroup() %>%
        dplyr::select(- method) %>%
        bind_cols(out_meta_df[no_batch_files,][i,]) 
    }) %>%
    purrr::reduce(bind_rows)
})
[1] "Outcome no.  1"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  2"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  3"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  4"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  5"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  6"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  7"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  8"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  9"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  10"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  11"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  12"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  13"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  14"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  15"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  16"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  17"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  18"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  19"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  20"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  21"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  22"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  23"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  24"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  25"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  26"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  27"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  28"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  29"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  30"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  31"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  32"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  33"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  34"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  35"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  36"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  37"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  38"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  39"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  40"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  41"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  42"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  43"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  44"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  45"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  46"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  47"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  48"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  49"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  50"

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  51"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  52"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  53"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  54"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  55"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  56"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  57"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  58"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  59"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  60"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  61"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  62"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  63"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  64"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  65"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  66"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  67"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  68"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  69"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  70"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  71"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  72"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  73"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  74"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  75"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  76"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  77"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  78"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  79"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  80"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  81"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  82"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  83"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  84"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  85"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  86"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  87"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  88"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  89"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  90"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  91"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  92"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  93"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  94"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  95"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  96"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  97"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  98"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  99"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  100"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  101"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  102"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  103"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  104"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  105"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  106"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  107"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  108"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  109"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  110"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  111"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  112"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  113"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  114"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  115"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  116"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  117"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  118"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  119"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  120"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  121"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  122"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  123"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  124"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  125"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  126"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  127"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  128"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  129"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  130"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  131"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  132"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  133"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  134"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  135"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  136"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  137"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  138"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  139"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  140"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  141"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  142"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  143"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
[1] "Outcome no.  144"

── Column specification ────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)

`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
outcome_df_2

pl_signal2noise <- function(mypop, myenr, myseed, mymethod){
    if (mymethod=="daseq") {
    pos_outcome <- "PosLFC"
  } else {
    pos_outcome <- "NegLFC"
  }
  popTPR <- outcome_df %>% filter(pop==mypop & enr==myenr & seed==myseed & method==mymethod) %>% pull(TPR)
  res_file <- list.files(outdir, 
                           pattern= paste0(".+",'embryo',"_pop_", mypop, "_enr",myenr,"_seed", myseed, '.+batchEffect0',".DAresults.",mymethod,".csv"),
                           full.names = TRUE)
  
  pl <- read_csv(res_file) %>%
    mutate(outcome = case_when(pred=="NotDA" & true_prob < 1-embryo_thresh ~ "FN",
                          pred==pos_outcome & true_prob < 1-embryo_thresh ~ "TP",
                          pred=="NotDA" & true_prob > 1-embryo_thresh ~ "TN"
                          )) %>%
    filter(outcome %in% c('TP', "FN")) %>%
    ggplot(aes(1 - true_prob, color=outcome)) +
    geom_density(size=1) +
    xlab("P(C1)") +
    ggtitle(paste("TPR = ", round(popTPR,2))) +
    theme_bw(base_size = 14)
  pl
}

pl_top <- wrap_plots(lapply(c(0.75, 0.85, 0.95), function(x) pl_signal2noise("Erythroid2", x, myseed = 43, mymethod = "milo")), ncol=3)

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)
pl_bot <- wrap_plots(lapply(c(0.75, 0.85, 0.95), function(x) pl_signal2noise("Caudal_neurectoderm", x, myseed = 43, mymethod = "milo")), ncol=3)

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)


── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  true_prob = col_double(),
  true = col_character(),
  method = col_character(),
  pred = col_character()
)
pl_B <- (pl_top / pl_bot) +
  plot_layout(guides = "collect") 

pl_B +
  ggsave(paste0(figdir,"Sfig_signal2noise.pdf"), height = 6, width = 9) +
  ggsave(paste0(figdir,"Sfig_signal2noise.png"), height = 6, width = 9)

Benchmark with batch effects

Read outcome for embryo (built with wrapper build_outcome.R)

outcome_df <- read_csv("/nfs/team205/ed6/data/milo_benchmark/outcome_embryo_v3_noBatch.csv")

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  FN = col_double(),
  TN = col_double(),
  TP = col_double(),
  FP = col_double(),
  TPR = col_double(),
  FPR = col_double(),
  TNR = col_double(),
  FNR = col_double(),
  FDR = col_double(),
  Precision = col_double(),
  Power = col_double(),
  Accuracy = col_double(),
  DA_thresh = col_double(),
  pop = col_character(),
  enr = col_double(),
  seed = col_double(),
  batchEffect = col_double(),
  method = col_character()
)

Read outcomes (made with wrapper build_outcome.R)

outcome_df_be <- read_csv("/nfs/team205/ed6/data/milo_benchmark/outcome_embryo_v3_wBatch.csv") %>%
  filter(pop!="Mixed_mesoderm")
Missing column names filled in: 'X19' [19]
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  FN = col_double(),
  TN = col_double(),
  TP = col_double(),
  FP = col_double(),
  TPR = col_double(),
  FPR = col_double(),
  TNR = col_double(),
  FNR = col_double(),
  FDR = col_double(),
  Precision = col_double(),
  Power = col_double(),
  Accuracy = col_double(),
  DA_thresh = col_double(),
  pop = col_character(),
  enr = col_double(),
  seed = col_double(),
  batchEffect = col_double(),
  method = col_character(),
  X19 = col_logical()
)
outcome_df <- bind_rows(outcome_df, outcome_df_be)
batch_labeller <- as_labeller(c(milo="Milo\n(~ batch + condition)", louvain="Louvain\n(~ batch + condition)", cydar="Cydar", daseq='DAseq'))

pl_df <- outcome_df %>%
  filter(method != "milo" & method != "louvain" & method != "cydar_batch") %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
          FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(method=str_remove(method,"_batch")) %>%
  filter(enr >= 0.8) %>%
  mutate(enr=as.character(enr)) 
  

p_top <- pl_df %>%
  ggplot(aes(as.factor(batchEffect), TPR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(.~method, labeller=batch_labeller) +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.x = element_blank())
  
p_bottom <- pl_df %>%
  ggplot(aes(as.factor(batchEffect), FDR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  xlab("Batch effect magnitude") +
  facet_grid(.~method, labeller=batch_labeller)

(p_top / p_bottom) + plot_layout(guides="collect") +
  ggsave(paste0(figdir, "main_bm_batch.pdf"), width = 11, height = 6) +
  ggsave(paste0(figdir, "main_bm_batch.png"), width = 11, height = 6)

Break down by logFC

pl_df <- outcome_df %>%
  filter(method != "milo" & method != "louvain" & method != "cydar_batch") %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
          FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(method=str_remove(method,"_batch")) %>%
  mutate(enr=as.character(enr)) 

p_top <- pl_df %>%
  ggplot(aes(as.factor(batchEffect), TPR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  facet_grid(enr~method, labeller=labeller(enr=enr_labeller2, method=batch_labeller)) +
  xlab("Batch effect magnitude") 
  
p_bottom <- pl_df %>%
  ggplot(aes(as.factor(batchEffect), FDR, color=method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  scale_fill_manual(values = method_colors, labels=setNames(method_labels, method_names)) +
  xlab("Batch effect magnitude") +
  facet_grid(enr~method, labeller=labeller(enr=enr_labeller2, method=batch_labeller))

(p_top | p_bottom) + plot_layout(guides="collect") + plot_annotation(tag_levels = c("A")) +
  # ggsave(paste0(figdir, "suppl_bm_batch_logFC.pdf"), width = 15, height = 10) +
  # ggsave(paste0(figdir, "suppl_bm_batch_logFC.png"), width = 15, height = 10)
  ggsave(paste0("~/mount/gdrive/milo/Figures/resubmission2/supplementary/suppl_fig_bm_batch.pdf"), width = 18, height = 10)

W and w/o batch control

pl_df <- outcome_df %>%
  filter(method %in% c("milo", "milo_batch")) %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
          FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(design = ifelse(str_detect(method,"_batch"), "~ batch + condition", "~ condition")) %>%
  filter(enr >= 0.8) %>%
  mutate(enr=as.character(enr))

metric='TPR'
pl_left <-pl_df %>%
  mutate(group=paste(method, design)) %>%
  mutate(method=str_remove(method, "_batch")) %>%
  ggplot(aes(as.factor(batchEffect), TPR, color =method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5)  +
  facet_grid(.~design) +
  theme_bw(base_size=16) +
  geom_hline(yintercept = 0.8, linetype=2) +
  # scale_color_manual(values = c(`~ condition`=method_colors["milo"], "black")) 
  scale_color_manual(values = method_colors, labels=c(milo="Milo", louvain="Louvain", cydar="Cydar"), name="") +
  theme(legend.position = "top", legend.justification = c(1,1)) +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.x = element_blank())

metric = "FDR"
pl_right <- 
  pl_df %>%
  mutate(group=paste(method, design)) %>%
  mutate(method=str_remove(method, "_batch")) %>%
  ggplot(aes(as.factor(batchEffect), FDR, color =method)) +
  geom_boxplot(outlier.alpha = 0) +
  ggbeeswarm::geom_quasirandom(alpha=0.5, position="stack", size=0.5)  +
  facet_grid(.~design) +
  xlab("Batch effect magnitude") +
  theme_bw(base_size=16) +
  geom_hline(yintercept = 0.1, linetype=2) +
  # scale_color_manual(values = c(`~ condition`=method_colors["milo"], "black")) 
  scale_color_manual(values = method_colors, labels=c(milo="Milo", louvain="Louvain", cydar="Cydar"), name="") +
  theme(legend.position = "top", legend.justification = c(1,1))


design_plot <- 
  (pl_left / pl_right) +
  plot_layout(guides="collect") &
  theme(legend.position = "top", legend.justification = c(1,1)) 

design_plot +
  ggsave(paste0(figdir, "batchEffect_design.png"), height = 6, width = 10) +
  ggsave(paste0(figdir, "batchEffect_design.pdf"), height = 6, width = 10, useDingbats=FALSE)

NA
NA

Plot examples

Visualize outcome in UMAP

  colData(embryo_sce) <- read_csv(coldata_file) %>% column_to_rownames() %>% DataFrame()

── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_character(),
  sample = col_double(),
  pool = col_double(),
  sequencing.batch = col_double(),
  doub.density = col_double(),
  doublet = col_logical(),
  cluster = col_double(),
  cluster.sub = col_double(),
  cluster.stage = col_double(),
  cluster.theiler = col_double(),
  stripped = col_logical(),
  sizeFactor = col_double(),
  Condition1_prob = col_double(),
  Condition2_prob = col_double()
)
ℹ Use `spec()` for the full column specifications.

Plot benchmark design

pl <- data.frame(reducedDim(sce, red_dim)) %>%
    dplyr::rename_all( ~ c("UMAP1", "UMAP2") ) %>%
    dplyr::mutate(method=method) %>%
    dplyr::mutate(predicted=factor(sce$predicted, levels=c("NegLFC", "PosLFC", 'NotDA'))) %>%
    dplyr::arrange(- predicted) %>%
    ggplot(aes(UMAP1, UMAP2, color=predicted)) + 
    geom_point_rast(size=0.1, raster.dpi = 500) +
    geom_point_rast(data= . %>% filter(predicted!="NotDA"), size=0.2, raster.dpi = 500) +
     scale_color_manual(values=c(NegLFC="red", NotDA="grey", PosLFC="blue"), 
                        labels=c(NegLFC="Enriched in C1", NotDA="No DA", PosLFC="Depleted in C1"), name='') +
     guides(color = guide_legend(override.aes = list(size=1))) +
     theme_classic(base_size=18) +
     theme(legend.position=c(.15,.2), axis.ticks = element_blank(),
           axis.text = element_blank()) +
     xlab("UMAP1") + ylab("UMAP2") +
      facet_wrap(method~.)  +
  remove_x_axis() + remove_y_axis() +
  theme(strip.text = element_blank()) +
  rasterize(geom_point(size=0.1), dpi = 300) +
  ggsave("~/mount/gdrive/milo/Figures/benchmark_v2/bm_design_pred_umap.pdf", width=4, height = 4)
‘-’ not meaningful for factors

Design matrix

Plot batch effect

library(ggrastr)
be_sce_ls <- lapply(c('0',"0.25", "0.5", "0.75", "1"), function(x) read_input_data(embryo_sce, indir, pop, enr, seed, x))

method="milo"

pop
## Plot condition probability 
be_pl_ls <- lapply(be_sce_ls, function(sce) {
  coldata_file <- list.files(indir, pattern=paste0(pop,".+", "enr",enr,".+",'seed', seed, ".coldata.csv"),
                           full.names = TRUE)
  colData(sce) <- DataFrame(read_csv(coldata_file) %>% column_to_rownames())
  data.frame(reducedDim(sce, "umap_batch")) %>%
rename(UMAP1=X1, UMAP2=X2) %>%
    mutate(true=sce$Condition1_prob) %>%
    mutate(true=ifelse(true < 0.5, 0.5, true)) %>%
    arrange(true) %>%
    ggplot(aes(UMAP1, UMAP2, color=true)) + 
    geom_point_rast(size=0.1, raster.dpi = 500) +
      scale_color_viridis_c(name="C1 probability") +
    theme_classic(base_size=14) +
      guides(color=guide_colorbar(title.position="left", title.hjust = 1, title.vjust = 1, barwidth = 0.5, barheight = 3)) +
     theme(axis.ticks = element_blank(),
           axis.text = element_blank(),
           legend.position = c(0.75,0.85), legend.background = element_blank()) +
     xlab("UMAP1") + ylab("UMAP2") 
  }
)


## Plot batch
be_pl_ls2 <- lapply(be_sce_ls, function(sce) {
  coldata_file <- list.files(indir, pattern=paste0(pop,".+", "enr",enr,".+",'seed', seed, ".coldata.csv"),
                           full.names = TRUE)
  colData(sce) <- DataFrame(read_csv(coldata_file) %>% column_to_rownames())
  data.frame(reducedDim(sce, "umap_batch")) %>%
    rename(UMAP1=X1, UMAP2=X2) %>%
    mutate(true=sce$synth_batches) %>%
    ggplot(aes(UMAP1, UMAP2, color=true)) +
    geom_point_rast(size=0.1, raster.dpi = 500) +
    scale_color_viridis_d(name="Batch", option="cividis") +
     theme_classic(base_size=18) +
      guides(color=guide_legend(override.aes = list(size=2))) +
     theme(axis.ticks = element_blank(),
           axis.text = element_blank()) +
     xlab("UMAP1") + ylab("UMAP2") 
  }
)

ptop <- wrap_plots(be_pl_ls, ncol=1, guides="collect") &
  theme(legend.position = "right") 
pbottom <- wrap_plots(be_pl_ls2, ncol=1, guides="collect")

(ptop | pbottom) +
  plot_layout(guides="collect") +
  ggsave(paste0(figdir, "batchEffect_UMAPs.pdf"), height=13, width = 8) +
  ggsave(paste0(figdir, "batchEffect_UMAPs.png"), height=13, width = 8)

Design matrix w batch effect

m1 <- data.frame(colData(sce)[,c("synth_labels", "synth_samples", 'synth_batches')]) %>%
  distinct(synth_labels,synth_samples) %>%
  mutate(synth_labels=str_remove(synth_labels,"ondition"),
         count=1) %>%
  pivot_wider(id_cols = synth_samples, names_from=synth_labels, values_from=count,values_fill=0) %>%
  pivot_longer(cols=c(C1, C2), names_to="synth_labels") %>%
  ggplot(aes(synth_labels, synth_samples)) +
  geom_tile(fill="white", color="black", size=1) +
  geom_tile(data=. %>% filter(value>0), aes(fill=synth_labels), color="black", size=1) +
  theme_classic(base_size=16)   +
  scale_fill_brewer(palette="Set1") +
  guides(fill='none') +
  xlab("Synthetic \ncondition") + ylab('Synthetic samples') +
  theme(axis.text.y = element_blank(),axis.ticks.y = element_blank(),
        axis.line = element_blank())

m2 <- data.frame(colData(sce)[,c("synth_labels", "synth_samples", 'synth_batches')]) %>%
  distinct(synth_labels,synth_samples, synth_batches) %>%
  mutate(synth_labels=str_remove(synth_labels,"ondition"),
         count=1) %>%
  pivot_wider(id_cols = synth_samples, names_from=synth_batches, values_from=count,values_fill=0) %>%
  pivot_longer(cols=c(B1, B2), names_to="synth_batches") %>%
  ggplot(aes(synth_batches, synth_samples)) +
  geom_tile(fill="white", color="black", size=1) +
  geom_tile(data=. %>% filter(value>0), aes(fill=synth_batches), color="black", size=1) +
  theme_classic(base_size=16)   +
  scale_fill_viridis_d(option="cividis") +
  guides(fill='none') +
  xlab("Synthetic \nbatch") + ylab('Synthetic samples') +
  theme(axis.text.y = element_blank(),axis.ticks.y = element_blank(), axis.title.y = element_blank(),
        axis.line = element_blank())

(m1 + m2) +
# (p1 + p2 + p3) + des_pl +
  plot_layout(widths=c(1,1), ncol=2) +
  ggsave(paste0(figdir, "bm_design_batch.pdf"), height = 4, width = 4)

Correcting batch effect

Load simulations with batch effects and correct with MNN

library(batchelor)

mnn_correct_batch_effect <- function(be_sce, k=50){
  ## Split in two SCE objects
  b1_be_sce <- be_sce[,be_sce$synth_batches=="B1"]
  b2_be_sce <- be_sce[,be_sce$synth_batches=="B2"]
  
  be_mnn <- reducedMNN(reducedDim(b1_be_sce, "pca.corrected"), reducedDim(b2_be_sce, "pca.corrected"), k=k)
  reducedDim(be_sce, "pca.MNN") <- be_mnn$corrected[colnames(be_sce),]
  be_sce
  }

## Simulate batch effects of different magnitude
save_corrected_be <- function(pop, pop_enr, seed, be_sd){
  ## Load coldata and PCA
  outdir <- '/nfs/team205/ed6/data/milo_benchmark/synthetic_data/'
  outprefix <- str_c("benchmark_embryo_pop_", pop, '_enr', pop_enr, "_seed", seed)
  coldata <- read_csv(paste0(outdir, outprefix, ".coldata.csv")) %>% column_to_rownames()
  X_pca <-read_csv(str_c(outdir, outprefix, "_batchEffect", be_sd, ".pca.csv")) %>% column_to_rownames()
  
  ## Add reduced dim + coldata to sce
  colData(embryo_sce) <- DataFrame(coldata)
  reducedDim(embryo_sce, "pca_batch") <- as.matrix(X_pca)
  
  set.seed(seed)
  sce_be <- mnn_correct_batch_effect(embryo_sce)
  X_pca <- reducedDim(sce_be, "pca.MNN")
  ## Save reduced dims
  write_csv(as.data.frame(X_pca) %>% rownames_to_column(), str_c(outdir, outprefix, "_batchEffect", be_sd,".MNNcorrected.pca.csv"))
  }

be_sds <- unique(out_meta_df$batchEffect)
pops <- unique(out_meta_df$pop)
seeds=c(43)

for (pop in pops) {
    for (seed in seeds) {
      for (be_sd in c(0.5, 0.75, 1)) {
      pop_enr = 0.8
      save_corrected_be(pop, pop_enr, seed, be_sd)
      }
    }
  }

Read all results (runned in wrapper submit_)

outdir <- "/nfs/team205/ed6/data/milo_benchmark/MNN_corrected/"
res_files <- list.files(outdir, pattern=".+DAresults.+.csv")
res_files_full <- list.files(outdir, pattern=".+DAresults.+.csv", full.names = TRUE)
# in_files <- list.files("~/data/milo_benchmark/synthetic_data/", pattern="_enr0.[78].+coldata.csv")

## Make data frame w benchmark parameters
mnn_out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed", "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove(batchEffect, "batchEffect")) 

## Load results
mnn_outcome_df <- lapply(seq_along(res_files_full), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[i]) %>%
      .outcome_by_prob(da_upper = embryo_thresh) %>%
      mutate(DA_thresh=embryo_thresh) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(mnn_out_meta_df[i,]) 
  pop_enr <- as.numeric(mnn_out_meta_df[i,"enr"])
  benchmark_df
  }) %>%
  purrr::reduce(bind_rows)
no_be <- outcome_df %>%
  filter(batchEffect=="0") %>%
  mutate(FDR = FP/(TP+FP)) 

uncorrected_be <- outcome_df %>%
  filter(batchEffect %in% c("0.5", "0.75", '1')) %>%
  mutate(FDR = FP/(TP+FP)) 

pl_df <- mnn_outcome_df %>%
  filter(enr > 0.6) %>%
   mutate(batchEffect = str_remove(batchEffect, ".MNNcorrected")) %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(pop=str_replace(pop, "_", " ")) %>%
  # mutate(pop_size=pop_sizes[pop])  %>%
  # arrange(pop_size) %>%
  mutate(pop=factor(pop, levels=unique(pop))) %>%
  mutate(seed=as.numeric(seed), enr=as.numeric(enr), batchEffect=as.numeric(batchEffect))

pl_top <- bind_rows(mutate(no_be, class="no Batch Effect"),
  mutate(uncorrected_be, class="Uncorrected"),
  mutate(pl_df, class="MNN corrected")) %>%
  mutate(class=factor(class, levels=c("no Batch Effect", "MNN corrected", "Uncorrected"))) %>%
    mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  filter(method != "milo_batch" & method !="louvain_batch" & method !="cydar_batch") %>%
  ggplot(aes(as.factor(batchEffect), color=method, TPR)) + 
  geom_boxplot(outlier.size = 0.5) +
  facet_grid(.~class, space="free", scales="free") +
  scale_color_methods() +
  scale_fill_methods() +
  theme_bw(base_size=16) +
  xlab("Batch effect magnitude") +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.x = element_blank())

pl_bottom <- bind_rows(mutate(no_be, class="no Batch Effect"),
  mutate(uncorrected_be, class="Uncorrected"),
  mutate(pl_df, class="MNN corrected")) %>%
  mutate(class=factor(class, levels=c("no Batch Effect", "MNN corrected", "Uncorrected"))) %>%
    mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  filter(method != "milo_batch" & method !="louvain_batch" & method !="cydar_batch") %>%
  ggplot(aes(as.factor(batchEffect), color=method, FDR)) + 
  geom_boxplot(outlier.size = 0.5) +
  facet_grid(.~class, space="free", scales="free") +
  scale_color_methods() +
  scale_fill_methods() +
  theme_bw(base_size=16) +
  xlab("Batch effect magnitude")

mnn_plot <- (pl_top / pl_bottom +
  plot_layout(guides="collect") &
  theme(legend.position="top")) +
  ggsave(paste0("~/mount/gdrive/milo/Figures/resubmission2/supplementary/suppl_fig_bm_MNN.pdf"), height = 6, width = 8) 
  
mnn_plot

(mnn_plot & theme(legend.position = "top")) + 
  # ggsave(paste0(figdir, "batchEffect_MNNcorrected.png"), height = 6, width = 10) +
  # ggsave(paste0(figdir, "batchEffect_MNNcorrected.pdf"), height = 6, width = 10) 
ggsave("~/mount/gdrive/milo/Figures/resubmission/supplementary/suppl_fig_bm_MNN.pdf", height = 6, width = 10)

Plot UMAP

X_pca_mnn <- read_csv("/nfs/team205/ed6/data/milo_benchmark/synthetic_data/benchmark_embryo_pop_Somitic_mesoderm_enr0.8_seed43_batchEffect0.75.MNNcorrected.pca.csv") %>%
  column_to_rownames()

all(rownames(X_pca_mnn) == colnames(embryo_sce))
coldata <- read_csv("/nfs/team205/ed6/data/milo_benchmark/synthetic_data/benchmark_embryo_pop_Somitic_mesoderm_enr0.8_seed43.coldata.csv")
colData(embryo_sce) <- coldata %>% column_to_rownames() %>% DataFrame()
reducedDim(embryo_sce, "pca_batch") <- as.matrix(X_pca_mnn)
embryo_sce <- runUMAP(embryo_sce, dimred="pca_batch", name="umap_batch")

indir <- "~/data/milo_benchmark/synthetic_data/"
res <- read_csv("/nfs/team205/ed6/data/milo_benchmark/benchmark_embryo_pop_Somitic_mesoderm_enr0.8_seed43_batchEffect0.75.DAresults.milo.csv")
embryo_sce$pred <- res$pred
embryo_sce$true <- res$true
plotReducedDim(embryo_sce, "umap_batch", colour_by="Condition1_prob", point_size=0.1)
plotReducedDim(embryo_sce, "umap_batch", colour_by="pred", point_size=0.1)
plotReducedDim(embryo_sce, "umap_batch", colour_by="true", point_size=0.1)

res %>%
  .outcome_by_prob(da_upper = 0.6) %>%
  mutate(FDR = FP/(TP+FP)) 

Show why Milo has TPR=0 if batch covariate not included.

data_id="embryo"
pop="Gut"
pop_enr="0.8"
seed='43'

## Load coldata and PCA
outdir <- '/nfs/team205/ed6/data/milo_benchmark/synthetic_data/'
outprefix <- str_c("benchmark_", data_id, "_pop_", pop, '_enr', pop_enr, "_seed", seed)
coldata <- read_csv(paste0(outdir, outprefix, ".coldata.csv")) %>% column_to_rownames()
X_pca <-read_csv(str_c(outdir, str_remove(outprefix, "_capped_logit.."), "_batchEffect", be_sd, ".pca.csv")) %>% column_to_rownames()  

## Find DA probability x cell
k=50
bm_params = list(
  milo = list(k=k)
  )


## Add reduced dim + coldata to sce
colData(embryo_sce) <- DataFrame(coldata)
reducedDim(embryo_sce, "pca_batch") <- as.matrix(X_pca)

## Run milo
milo_res <- run_milo(embryo_sce, condition_col="synth_labels", sample_col='synth_samples',
                       reduced.dim = "pca_batch", d=30, k=bm_params$milo$k)

design_df <- as.tibble(colData(embryo_sce)[c('synth_samples', "synth_labels")]) %>%
    distinct() %>%
    column_to_rownames('synth_samples')

plotNhoodMA(milo_res$DAres)

ggplot(milo_res$DAres, aes(PValue)) + geom_histogram()

out <- milo2output(milo_res$Milo, milo_res$DAres, out_type = out_type)
head(nhoodCounts(milo_res$Milo)[,design_df$synth_labels=="Condition1"])

Non-linear batch effect

add_batch_effect_nonlinear <- function(sce, batch_col="synth_batches", theta_deg=20, dims=1:2){
  ## Simulate rotation of first 2 PCs
  theta=theta_deg*pi/180
  rotM=matrix(0,nrow=2,ncol=2)
  rotM[1,]=c(cos(theta),-sin(theta))
  rotM[2,]=c(sin(theta),cos(theta))
  
  cellids_sample <- split(sce$cell, sce[[batch_col]])
  X_pca <- reducedDim(sce, "pca.corrected")
  X_pca_batch <- X_pca
  ## Apply rotation to one of the batches
  X_pca_batch[cellids_sample[[names(cellids_sample)[1]]],dims] <- t(rotM %*% t(X_pca_batch[cellids_sample[[names(cellids_sample)[1]]],dims]))
  reducedDim(sce, "pca_batch") <- X_pca_batch
  sce  
  }

coldata_file <- list.files(indir, pattern=paste0(pop,".+", "enr",enr,".+",'seed', seed, ".coldata.csv"),
                           full.names = TRUE)
colData(embryo_sce) <- read_csv(coldata_file) %>% column_to_rownames() %>% DataFrame()
  
batch_col="synth_batches"

embryo_sce <- add_batch_effect_nonlinear(embryo_sce, dims=c(3,5), theta_deg = 30)
embryo_sce <- runUMAP(embryo_sce, dimred="pca_batch", name = 'umap_batch', n_dimred=1:30)  

data.frame(reducedDim(embryo_sce, "umap_batch")) %>%
    rename(UMAP1=X1, UMAP2=X2) %>%
    mutate(true=embryo_sce$synth_batches) %>%
    ggplot(aes(UMAP1, UMAP2, color=true)) +
    geom_point(size=0.1) +
    scale_color_viridis_d(name="Batch", option="cividis") +
     theme_classic(base_size=18) +
      guides(color=guide_legend(override.aes = list(size=2))) +
     theme(axis.ticks = element_blank(),
           axis.text = element_blank()) +
     xlab("UMAP1") + ylab("UMAP2")

data.frame(reducedDim(embryo_sce, "UMAP")) %>%
    rename(UMAP1=X1, UMAP2=X2) %>%
    mutate(true=embryo_sce$synth_batches) %>%
    ggplot(aes(UMAP1, UMAP2, color=true)) +
    geom_point(size=0.1) +
    scale_color_viridis_d(name="Batch", option="cividis") +
     theme_classic(base_size=18) +
      guides(color=guide_legend(override.aes = list(size=2))) +
     theme(axis.ticks = element_blank(),
           axis.text = element_blank()) +
     xlab("UMAP1") + ylab("UMAP2")


# be_sce_ls <- lapply(c('0',"0.25", "0.5", "0.75", "1"), function(x) read_input_data(embryo_sce, indir, pop, enr, seed, x, run_umap = FALSE))

Make non-linear batch effect for all populations

## Simulate batch effects of different magnitude
save_nonlinear_be <- function(sce, pop, pop_enr, seed){
  ## Load coldata and PCA
  outdir <- '/nfs/team205/ed6/data/milo_benchmark/synthetic_data/'
  outprefix <- str_c("benchmark_embryo_pop_", pop, '_enr', pop_enr, "_seed", seed)
  coldata <- read_csv(paste0(outdir, outprefix, ".coldata.csv")) %>% column_to_rownames()
  ## Add reduced dim + coldata to sce
  colData(sce) <- DataFrame(coldata)
  
  set.seed(seed)
  sce_be <- add_batch_effect_nonlinear(embryo_sce, dims=c(3,5), theta_deg = 30)
  X_pca <- reducedDim(sce_be, "pca_batch")
  ## Save reduced dims
  write_csv(as.data.frame(X_pca) %>% rownames_to_column(), str_c(outdir, outprefix, "_batchEffectNonLinear30.pca.csv"))
  }

pops <- unique(out_meta_df$pop)
pop_enrs <- unique(out_meta_df$enr)
seeds <- unique(out_meta_df$seed)

for (pop in pops) {
  for (pop_enr in pop_enrs[1:3]) {
    for (seed in seeds) {
      save_nonlinear_be(embryo_sce, pop, pop_enr, seed)
    }
  }
}

Running in run_DA_nonlinear.R.

Read all results

outdir <- "/nfs/team205/ed6/data/milo_benchmark/"
res_files <- list.files(outdir, pattern="NonLinear.+DAresults.+.csv")
res_files_full <- list.files(outdir, pattern="NonLinear.+DAresults.+.csv", full.names = TRUE)

## Make data frame w benchmark parameters
nonl_out_meta_df <- data.frame(file_id = str_remove_all(res_files, "benchmark_embryo_pop_|.csv")) %>%
  separate(col = file_id, sep = ".DAresults.", into=c("file_id", "method")) %>%
  separate(col = file_id, sep = "_enr", into=c("pop", "file_id")) %>%
  separate(col = file_id, sep = "_", into=c("enr", "seed", "batchEffect")) %>%
  mutate(seed=str_remove(seed, "seed"), batchEffect=str_remove(batchEffect, "batchEffect"))

## Load results
nonl_outcome_df <- lapply(seq_along(res_files_full), function(i){ 
  print(paste("Outcome no. ", i))
  benchmark_df <- read_csv(res_files_full[i]) %>%
      .outcome_by_prob(da_upper = 0.6) %>%
      mutate(DA_thresh=0.6) %>%
      ungroup() %>%
      dplyr::select(- method) %>%
      bind_cols(nonl_out_meta_df[i,]) 
  pop_enr <- as.numeric(nonl_out_meta_df[i,"enr"])
  benchmark_df
  }) %>%
  purrr::reduce(bind_rows)

nonl_outcome_df 
pl_df <- nonl_outcome_df %>%
  filter(enr > 0.6) %>%
  mutate(FDR = FP/(TP+FP)) %>%
  mutate(TPR=ifelse(is.nan(TPR), 0, TPR),
         FPR=ifelse(is.nan(FPR), 0, FPR),
         FDR=ifelse(is.nan(FDR), 0, FDR),
         Precision=ifelse(is.nan(Precision), 0, Precision)) %>%
  mutate(pop=str_replace(pop, "_", " ")) 

pl_df %>%
  ggplot(aes(pop, TPR)) + 
  ggbeeswarm::geom_quasirandom(alpha=0.5) +
  geom_hline(yintercept = 0.8, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_brewer(palette="Dark2") +
  facet_grid(enr~., labeller = enr_labeller) +
pl_df %>%
  ggplot(aes(pop, FDR)) + 
  ggbeeswarm::geom_quasirandom(alpha=0.5) +
  geom_hline(yintercept = 0.1, linetype=2) +
  theme_bw(base_size = 16) +
  scale_color_brewer(palette="Dark2") +
  facet_grid(enr~., labeller = enr_labeller) +
plot_layout(guides='collect') 
lin_be <- outcome_df %>%
  filter(method=="milo_batch" & enr %in% c(0.7, 0.8) & DA_thresh==0.6)

bind_rows(
  mutate(lin_be, class="Linear batch effect"),
  mutate(nonl_outcome_df, class="Non Linear\n batch effect") %>%
    filter(enr > 0.6) %>%
    mutate(enr=as.numeric(enr), seed=as.numeric(seed), batchEffect=as.numeric(str_remove(batchEffect, "NonLinear"))) 
  ) %>%
  ggplot(aes(as.factor(batchEffect), TPR, color=method)) +
  geom_boxplot() +
  ggbeeswarm::geom_quasirandom(alpha=0.5) +
  facet_grid(enr~class, scales="free", space="free") +
  scale_color_manual(values=method_colors[[4]], labels=setNames(method_labels, method_names)) +
  theme_bw(base_size=16) +
  xlab("Batch effect magnitude")

Louvain on iterative subclustering

plotUMAP(embryo_sce, colour_by="Condition1_prob")

Subcluster all celltype populations (there is a caveat here that I am not recalculating the PCA space for all subsets, but it should bring home the message regardless)

embryo_sce$subcluster <- NA
k=15

for (pop in unique(embryo_sce$celltype)) {
  pop_sce <- embryo_sce[,embryo_sce$celltype==pop]
  X_red_dim <- reducedDim(pop_sce, "pca.corrected")
  sce.graph <- buildKNNGraph(t(X_red_dim), k=k)
  louvain.clust <- cluster_louvain(sce.graph)
  louvain.clust.ids <- membership(louvain.clust)
  pop_sce$subcluster <- paste(pop, as.character(louvain.clust.ids), sep="_")
  subclusters <- setNames(pop_sce$subcluster, colnames(pop_sce))
  colData(embryo_sce)["subcluster"][names(subclusters),] <- subclusters
  }

# pop_sce <- runUMAP(pop_sce, dimred="pca.corrected")
subclusters_umap <- data.frame(reducedDim(embryo_sce, "UMAP")) %>%
  mutate(subcluster=embryo_sce$subcluster) %>%
  mutate(subcluster=factor(subcluster, levels=sample(unique(subcluster)))) %>%
  ggplot(aes(X1, X2, color=subcluster)) +
  geom_point(size=0.1) +
  guides(color="none") +
  xlab("UMAP1") + ylab("UMAP2") +
  theme_classic(base_size=18)

Make simulated labels

embryo_sce <- add_synthetic_labels_pop(embryo_sce, pop="Somitic mesoderm", pop_column = "celltype", seed=42, pop_enr=0.8)
true_labels <- ifelse(embryo_sce$Condition2_prob < 0.4, "NegLFC", ifelse(embryo_sce$Condition2_prob > 0.6, "PosLFC", "NotDA"))
colData(embryo_sce)[["true_labels"]] <- true_labels

Testing for DA with GLM on subclusters

condition_col = "synth_labels"
sample_col = "synth_samples"
sce <- embryo_sce

## Make design matrix
design_df <- as.tibble(colData(sce)[c(sample_col, condition_col)]) %>%
    distinct() %>%
    rename(sample=sample_col)
design <- formula(paste('Freq ~', condition_col, "+ offset(log(N_s))", collapse = ' '))  

## Test DA in subclusters
condition_vec <- colData(embryo_sce)[[condition_col]]
sample_labels <- colData(embryo_sce)[[sample_col]]
clust.df <- data.frame("cell_id"=colnames(embryo_sce), "Louvain.Clust"=embryo_sce$subcluster)
clust.df$Sample <- sample_labels
clust.df$Condition <- condition_vec

louvain.count <- table(clust.df$Louvain.Clust, clust.df$Sample)
attributes(louvain.count)$class <- "matrix"
  
df <- melt(louvain.count, varnames=c("cluster", "sample"),  value.name="Freq") %>%
    mutate(cluster=factor(cluster)) %>%
    left_join(design_df, by="sample") %>%
    group_by(sample) %>%
    mutate(N_s=sum(Freq)) %>%
    ungroup() %>%
    group_by(cluster) %>%
    do(model=glm(design, data=., family="poisson")) 
  
res_df <- t(sapply(df$model, function(x) summary(x)$coefficients[nrow(summary(x)$coefficients),]))
colnames(res_df) <- c("logFC","Std. Error", "z value",    "Pval" )
louvain.res <- cbind(df, res_df) %>%
  mutate(FDR=p.adjust(Pval, method = "BH"))
rownames(louvain.res) <- louvain.res$cluster
  
clust.df$logFC <- louvain.res[clust.df$Louvain.Clust, 'logFC']
clust.df$FDR <- louvain.res[clust.df$Louvain.Clust, 'FDR']
embryo_sce$predDA_subclusters <- louvain2output(clust.df, out_type = "labels")

clust.df %>%
  ggplot(aes(logFC, -log10(FDR))) + geom_point()
## Test DA in cell type clusters
clust.df <- data.frame("cell_id"=colnames(embryo_sce), "Louvain.Clust"=embryo_sce$celltype)
clust.df$Sample <- sample_labels
clust.df$Condition <- condition_vec

louvain.count <- table(clust.df$Louvain.Clust, clust.df$Sample)
attributes(louvain.count)$class <- "matrix"
  
df <- melt(louvain.count, varnames=c("cluster", "sample"),  value.name="Freq") %>%
    mutate(cluster=factor(cluster)) %>%
    left_join(design_df, by="sample") %>%
    group_by(sample) %>%
    mutate(N_s=sum(Freq)) %>%
    ungroup() %>%
    group_by(cluster) %>%
    do(model=glm(design, data=., family="poisson")) 
  
res_df <- t(sapply(df$model, function(x) summary(x)$coefficients[nrow(summary(x)$coefficients),]))
colnames(res_df) <- c("logFC","Std. Error", "z value",    "Pval" )
louvain.res <- cbind(df, res_df) %>%
  mutate(FDR=p.adjust(Pval, method = "BH"))
rownames(louvain.res) <- louvain.res$cluster
  
clust.df$logFC <- louvain.res[clust.df$Louvain.Clust, 'logFC']
clust.df$FDR <- louvain.res[clust.df$Louvain.Clust, 'FDR']
embryo_sce$predDA_celltype <- louvain2output(clust.df, out_type = "labels")

clust.df %>%
  ggplot(aes(logFC, -log10(FDR))) + geom_point()
milo_res <- run_milo(embryo_sce, condition_col="synth_labels", sample_col="synth_samples", reduced.dim = "pca.corrected",
        k=50, d = 30)


embryo_sce$predDA_milo <- milo2output(milo_res$Milo, milo_res$DAres, out_type = "labels", alpha = 0.1)
# embryo_sce$predDA <- louvain2output(clust.df, out_type = "labels")

pl_df <- data.frame(reducedDim(embryo_sce, "UMAP")) %>%
  mutate(subcluster=embryo_sce$subcluster) %>%
  mutate(subcluster=factor(subcluster, levels=sample(unique(subcluster)))) %>%
  mutate(predDA_subclusters=embryo_sce$predDA_subclusters,
         predDA_celltype=embryo_sce$predDA_celltype,
         predDA_milo=embryo_sce$predDA_milo,
         trueDA = embryo_sce$true_labels) 

true_pl <- pl_df %>%
  ggplot(aes(X1, X2, color=trueDA)) +
  geom_point(size=0.1) +
  xlab("UMAP1") + ylab("UMAP2") +
  theme_classic(base_size=18) +
  scale_color_manual(values=c(NotDA="grey", PosLFC="Red", NegLFC="Blue"),name="") +
  guides(color="none") +
  ggtitle("True DA")

subcl_plot <- pl_df %>%
  ggplot(aes(X1, X2, color=predDA_subclusters)) +
  geom_point(size=0.1) +
  xlab("UMAP1") + ylab("UMAP2") +
  theme_classic(base_size=18) +
  scale_color_manual(values=c(NotDA="grey", PosLFC="Red", NegLFC="Blue"),name="") +
  guides(color=guide_legend(override.aes = c(size=2))) +
  ggtitle("GLM on subclusters")

cl_plot <- pl_df %>%
  ggplot(aes(X1, X2, color=predDA_celltype)) +
  geom_point(size=0.1) +
  xlab("UMAP1") + ylab("UMAP2") +
  theme_classic(base_size=18) +
  scale_color_manual(values=c(NotDA="grey", PosLFC="Red", NegLFC="Blue"),name="") +
  guides(color="none") +
  ggtitle("GLM on clusters")

milo_pl <- pl_df %>%
  ggplot(aes(X1, X2, color=predDA_milo)) +
  geom_point(size=0.1) +
  xlab("UMAP1") + ylab("UMAP2") +
  theme_classic(base_size=18) +
  scale_color_manual(values=c(NotDA="grey", PosLFC="Red", NegLFC="Blue"), name="") +
  guides(color="none") +
  ggtitle("Milo")

fig2 <- true_pl + milo_pl + cl_plot + subcl_plot +
  plot_layout(ncol=2, nrow=2, guides="collect") 

Compare size of subclusters and size of neighbourhoods

size_fig <- (data.frame(table(embryo_sce$subcluster)) %>%
  ggplot(aes(Freq)) + geom_histogram() +
  theme_classic(base_size = 16) +
   annotate("text", label=paste0("N = ", length(unique(embryo_sce$subcluster))), x=750, y=20, size=5) +
   xlab("Subcluster size") +
  xlim(0, 1000)) /
(plotNhoodSizeHist(milo_res$Milo) +
  xlim(0, 1000) +
   annotate("text", label=paste0("N = ", ncol(nhoods(milo_res$Milo))), x=750, y=600, size=5) +
   xlab("Milo neighbourhood size"))

size_fig
((((subclusters_umap + ggtitle("Subclusters")) /  size_fig) + plot_layout(ncol=1)) |
   fig2 ) +
  plot_layout(ncol=2, widths=c(1,2)) +
  plot_annotation(tag_levels = 'A') +
  ggsave("~/mount/gdrive/milo/Figures/RebuttalFig1_microclusters.png", width = 14, height = 8)
LS0tCnRpdGxlOiAiQmVuY2htYXJraW5nIERBIG1ldGhvZHMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKIyBsaWJyYXJ5KE1vdXNlR2FzdHJ1bGF0aW9uRGF0YSkKbGlicmFyeShTaW5nbGVDZWxsRXhwZXJpbWVudCkKbGlicmFyeShzY2F0ZXIpCmxpYnJhcnkoc2NyYW4pCmxpYnJhcnkoYml0NjQpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGdncHVicikKCnNvdXJjZSgnfi9taWxvL25vdGVib29rcy9iZW5jaG1hcmsvYmVuY2htYXJrX3V0aWxzLlInKQpgYGAKCmBgYHtyfQpmaWdkaXIgPC0gIn4vbW91bnQvZ2RyaXZlL21pbG8vRmlndXJlcy9iZW5jaG1hcmtfdjIvIgppZiAoIWRpci5leGlzdHMoZmlnZGlyKSkgewogIGRpci5jcmVhdGUoZmlnZGlyKSAgCn0KCmBgYAoKU29tZSBwbG90dGluZyB1dGlscwoKYGBge3J9CiMjIGNvbG9yIHBhbGV0dGUgZm9yIG1ldGhvZHMKbWV0aG9kX25hbWVzIDwtIGMoIm1pbG8iLCAiZGFzZXEiLCAibWVsZCIsICJsb3V2YWluIiwgImN5ZGFyIikKbWV0aG9kX2NvbG9ycyA8LSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoNywgbmFtZT0iRGFyazIiKVtjKDE6NCw2KV0KbWV0aG9kX2NvbG9ycyA8LSBzZXROYW1lcyhtZXRob2RfY29sb3JzLCBtZXRob2RfbmFtZXMpCm1ldGhvZF9sYWJlbHMgPC0gYygiTWlsbyIsICJEQXNlcSIsICJNRUxEIiwgIkxvdXZhaW4iLCAiY3lkYXIiKQptZXRob2RfbGFiZWxzIDwtIHNldE5hbWVzKG1ldGhvZF9sYWJlbHMsIG1ldGhvZF9uYW1lcykKCnNjYWxlX2NvbG9yX21ldGhvZHMgPC0gZnVuY3Rpb24oKXsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1tZXRob2RfbGFiZWxzKSB9CnNjYWxlX2ZpbGxfbWV0aG9kcyA8LSBmdW5jdGlvbigpeyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9bWV0aG9kX2xhYmVscykgfQoKcmVtb3ZlX3hfYXhpcyA8LSBmdW5jdGlvbigpewogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgIAp9CgpyZW1vdmVfeV9heGlzIDwtIGZ1bmN0aW9uKCl7CiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSAgCn0KYGBgCgpgYGB7cn0KZW5yX2xhYmVsbGVyMiA8LSBmdW5jdGlvbih2YWx1ZSl7CiAgZmMgPC0gcm91bmQocHJvYjJGQyhhcy5udW1lcmljKHZhbHVlKSksIDIpCiAgZW5yX25hbWUgPC0gcGFzdGUoImxvZ0ZDID0gIiwgZmMpCiAgcmV0dXJuKGModmFsdWU9ZW5yX25hbWUpKQp9CgpwbF9sYWJlbGxlciA8LSBsYWJlbGxlcihtZXRob2Q9YXNfbGFiZWxsZXIoc2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSksCiAgICAgZW5yPWVucl9sYWJlbGxlcjIpCmBgYAoKCkluIHRoaXMgbm90ZWJvb2sgSSB3aWxsIHZpc3VhbGl6ZSB0aGUgcmVzdWx0cyBmcm9tIGJlbmNobWFya2luZyBNaWxvIGFnYWluc3QgNCBhbHRlcm5hdGl2ZSBEQSBhbmFseXNpcyBtZXRob2RzLgoKIyMgQmVuY2htYXJraW5nIHdvcmtmbG93CgpBbGwgdGhlIG1haW4gZnVuY3Rpb25zIGFyZSBpbXBsZW1lbnRlZCBpbiBgYmVuY2htYXJrL2JlbmNobWFya191dGlscy5SYC4gVGhlc2UgZnVuY3Rpb25zIGFyZSB3cmFwcGVkIGluIHNldmVyYWwgc2NyaXB0czoKCi0gQ29uZGl0aW9uIGxhYmVscyBhcmUgc2ltdWxhdGVkIGJ5IHJ1bm5pbmcgYG1ha2VfYm1fZGF0YS5SYCAod3JhcHBlZCBpbiBgc3VibWl0X21ha2VfYm1fZGF0YS5zaGApCi0gTWV0aG9kcyBpbXBsZW1lbnRlZCBpbiBSIGFyZSBydW4gd2l0aCBgcnVuX0RBX1IucmAgCi0gTUVMRCBpcyBydW4gaW4gYHJ1bl9tZWxkLnB5YAotIEFsbCBvZiBpdCBpcyB3cmFwcGVkIGluIGBzdWJtaXRfYmVuY2htYXJrLnNoYCAoY29udGFpbnMgcGFyYW1ldGVycyBmb3IgZWFjaCBpbnB1dCBkYXRhc2V0KQoKIyMgRGVmaW5lIGlucHV0IGRhdGFzZXRzCgpUaGVzZSBhcmUgZ29pbmcgdG8gYmUgdXNlZCBhcyB1bmRlcmx5aW5nIEtOTiBncmFwaHMgd2l0aCBkaWZmZXJlbnQgdG9wb2xvZ2llcyBmb3IgYmVuY2htYXJraW5nLgoKIyMjIFNpbXVsYXRlZCBkYXRhc2V0cwoKUHJvdmlkZWQgYnkgTWlrZSwgY29uc3RydWN0ZWQgd2l0aCBgZHludG95YAoKUHJlcGFyZSBkYXRhc2V0cyAodW5pZm9ybSBuYW1pbmcgb2YgZGltIHJlZHVjdGlvbiBhbmQgY2VsbHR5cGUgY29sdW1uKQpgYGB7cn0KYnJhbmNoX3NjZV8zeCA8LSByZWFkUkRTKCJ+L21vdW50L2dkcml2ZS9taWxvL0JyYW5jaGluZ1NpbXVsYXRpb24tM1guUkRTIikKYnJhbmNoX3NjZV8zeCRjZWxsIDwtIGNvbG5hbWVzKGJyYW5jaF9zY2VfM3gpCmJyYW5jaF9zY2VfM3gkY2VsbHR5cGUgPC0gYnJhbmNoX3NjZV8zeCRncm91cF9pZApuYW1lcyhyZWR1Y2VkRGltcyhicmFuY2hfc2NlXzN4KSkgPC0gYygicGNhLmNvcnJlY3RlZCIsICJVTUFQIikKc2F2ZVJEUyhicmFuY2hfc2NlXzN4LCAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2JyYW5jaGluZzN4X2RhdGFfYm0uUkRTIikKCmxpbmVhcl9zY2VfM3ggPC0gcmVhZFJEUygifi9tb3VudC9nZHJpdmUvbWlsby9MaW5lYXJUcmFqU3ludGhldGljTGFiZWxzLTNYLlJEUyIpCmxpbmVhcl9zY2VfM3gkY2VsbCA8LSBjb2xuYW1lcyhsaW5lYXJfc2NlXzN4KQpsaW5lYXJfc2NlXzN4JGNlbGx0eXBlIDwtIGxpbmVhcl9zY2VfM3gkZ3JvdXBfaWQKbmFtZXMocmVkdWNlZERpbXMobGluZWFyX3NjZV8zeCkpIDwtIGMoInBjYS5jb3JyZWN0ZWQiLCAiVU1BUCIpCnNhdmVSRFMobGluZWFyX3NjZV8zeCwgIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9saW5lYXIzeF9kYXRhX2JtLlJEUyIpCgpjbHVzdGVyX3NjZV8zeCA8LSByZWFkUkRTKCJ+L21vdW50L2dkcml2ZS9taWxvL0Rpc2NyZXRlU3ludGhldGljTGFiZWxzLTNYLlJEUyIpCmNsdXN0ZXJfc2NlXzN4JGNlbGwgPC0gY29sbmFtZXMoY2x1c3Rlcl9zY2VfM3gpCmNsdXN0ZXJfc2NlXzN4JGNlbGx0eXBlIDwtIGNsdXN0ZXJfc2NlXzN4JEJsb2NrCm5hbWVzKHJlZHVjZWREaW1zKGNsdXN0ZXJfc2NlXzN4KSkgPC0gYygicGNhLmNvcnJlY3RlZCIsICJVTUFQIikKc2F2ZVJEUyhjbHVzdGVyX3NjZV8zeCwgIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9jbHVzdGVyM3hfZGF0YV9ibS5SRFMiKQpgYGAKCiMjIyBNb3VzZSBnYXN0cnVsYXRpb24gZGF0YQoKU2VsZWN0IHNhbXBsZXMgZnJvbSBsYXRlIHRpbWUgcG9pbnRzIChldmVuIG51bWJlciBvZiByZXBsaWNhdGVzKQoKYGBge3J9CkF0bGFzU2FtcGxlTWV0YWRhdGEgJT4lCiAgYXJyYW5nZShzdGFnZSkgJT4lCiAgbXV0YXRlKHNhbXBsZT1mYWN0b3Ioc2FtcGxlLCBsZXZlbHM9dW5pcXVlKHNhbXBsZSkpKSAlPiUKICBnZ3Bsb3QoYWVzKHN0YWdlLCBzYW1wbGUpKSArCiAgZ2VvbV9wb2ludCgpCgpsYXRlX3NhbXBsZXMgPC0gQXRsYXNTYW1wbGVNZXRhZGF0YSAlPiUKICBmaWx0ZXIoc3RhZ2UgJWluJSBjKCJFNy43NSIsICJFOC4wIiwgIkU4LjI1IiwgIkU4LjUiKSkgJT4lCiAgcHVsbChzYW1wbGUpCmBgYAoKYGBge3J9CmVtYnJ5b19zY2UgPC0gRW1icnlvQXRsYXNEYXRhKHR5cGU9InByb2Nlc3NlZCIsIHNhbXBsZXMgPSBsYXRlX3NhbXBsZXMpCmBgYAoKYGBge3J9CmRhdGEuZnJhbWUoY29sRGF0YShlbWJyeW9fc2NlKSkgJT4lCiAgZ2dwbG90KGFlcyhhcy5mYWN0b3Ioc2FtcGxlKSwgYXMuZmFjdG9yKHBvb2wpKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZW1icnlvX3NjZQpgYGAKClByZXByb2Nlc3NpbmcKCmBgYHtyfQpsb2djb3VudHMoZW1icnlvX3NjZSkgPC0gbG9nMXAoY291bnRzKGVtYnJ5b19zY2UpKQojIyBFeGNsdWRlIHplcm8gY291bnRzIGdlbmVzCmtlZXAucm93cyA8LSByb3dTdW1zKGxvZ2NvdW50cyhlbWJyeW9fc2NlKSkgIT0gMAplbWJyeW9fc2NlIDwtIGVtYnJ5b19zY2Vba2VlcC5yb3dzLCBdCgpkZWMgPC0gbW9kZWxHZW5lVmFyKGVtYnJ5b19zY2UpCmh2Z3MgPC0gZ2V0VG9wSFZHcyhkZWMsIG49NTAwMCkKCiMjIERyb3AgY2VsbHMgd2l0aCBOQXMgaW4gY29ycmVjdGVkIHBjYSAobG93IHF1YWxpdHkpCmVtYnJ5b19zY2UgPC0gZW1icnlvX3NjZVssYXBwbHkocmVkdWNlZERpbShlbWJyeW9fc2NlLCAicGNhLmNvcnJlY3RlZCIpLCAxLCBmdW5jdGlvbih4KSBhbGwoIWlzLm5hKHgpKSldCgojIyBSdW4gVU1BUCAodGhlIGRhdGEgaGFzIGJlZW4gc3Vic2V0dGVkKQojIGVtYnJ5b19zY2UgPC0gc2NhdGVyOjpydW5QQ0EoZW1icnlvX3NjZSwgc3Vic2V0X3Jvdz1odmdzKQplbWJyeW9fc2NlIDwtIHNjYXRlcjo6cnVuVU1BUChlbWJyeW9fc2NlLCBkaW1yZWQ9InBjYS5jb3JyZWN0ZWQiKQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KcGxvdFJlZHVjZWREaW0oZW1icnlvX3NjZSwgIlVNQVAiLCBjb2xvdXJfYnk9ImNlbGx0eXBlIiwgdGV4dF9ieT0iY2VsbHR5cGUiLCBwb2ludF9zaXplPTAuMSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9RW1icnlvQ2VsbHR5cGVDb2xvdXJzKSArCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9MikpKQpgYGAKClNhdmUgb2JqZWN0IDQgYmVuY2htYXJrCgpgYGB7cn0Kc2F2ZVJEUyhlbWJyeW9fc2NlLCAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2VtYnJ5b19kYXRhX2JtLlJEUyIpCmBgYAoKYGBge3J9CmVtYnJ5b19zY2UgPC0gcmVhZFJEUygiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2VtYnJ5b19kYXRhX2JtLlJEUyIpCmBgYAoKU2F2ZSBsaXN0IG9mIGNlbGx0eXBlIG5hbWVzIGFuZCBzYW1wbGUgYnkgc2l6ZXMKCmBgYHtyfQpmb3IgKGkgaW4gMTozKSB7CiAgcG9wX3NpemVfZGYgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShlbWJyeW9fc2NlJGNlbGx0eXBlKSkgJT4lCiAgcmVuYW1lKHBvcD1WYXIxLCBwb3Bfc2l6ZT1GcmVxKSAlPiUKICBtdXRhdGUoc2l6ZV9iaW4gPSBjdXQocG9wX3NpemUsIGJyZWFrcyA9IDEwKSkgJT4lCiAgZ3JvdXBfYnkoc2l6ZV9iaW4pICU+JQogIHNhbXBsZV9uKHNpemU9MSkgCiAgd3JpdGUoYXMuY2hhcmFjdGVyKHBvcF9zaXplX2RmJHBvcCksIGdsdWUoIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9wb3Bfc2FtcGxlX3tpfS50eHQiKSkKfQpgYGAKClNhbml0eSBjaGVjayBvZiBzeW50aGV0aWMgbGFiZWxzIG9uIGVtYnJ5byBkYXRhCgpgYGB7cn0KcG9wcyA8LSBzY2FuKCIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvcG9wX3NhbXBsZV8yX2NsZWFuLnR4dCIsIHdoYXQ9IiIpCnVtYXBfbHMgPC0gbGFwcGx5KHBvcHMsIGZ1bmN0aW9uKHApewogIGZpbGVuYW1lIDwtIHBhc3RlMCgnL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL3N5bnRoZXRpY19kYXRhL2JlbmNobWFya19lbWJyeW9fcG9wXycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3JlcGxhY2UocCwgIiAiLCAiXyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdfZW5yMC44X3NlZWQ0NS5jb2xkYXRhLmNzdicpCiAgaWYgKGZpbGUuZXhpc3RzKGZpbGVuYW1lKSl7CiAgICBjb2xkYXRhIDwtIHJlYWRfY3N2KGZpbGVuYW1lKQogICAgY29sRGF0YShlbWJyeW9fc2NlKSA8LSBjb2x1bW5fdG9fcm93bmFtZXMoY29sZGF0YSkgJT4lIERhdGFGcmFtZSgpCiAgICBkYXRhLmZyYW1lKHJlZHVjZWREaW0oZW1icnlvX3NjZSwgJ1VNQVAnKSkgJT4lCiAgICAgIGRwbHlyOjpyZW5hbWUoVU1BUDE9WDEsIFVNQVAyPVgyKSAlPiUKICAgICAgbXV0YXRlKENvbmRpdGlvbjFfcHJvYj1lbWJyeW9fc2NlJENvbmRpdGlvbjFfcHJvYiA+IDAuNikgJT4lCiAgICAgIGdncGxvdChhZXMoVU1BUDEsIFVNQVAyLCBjb2xvcj1Db25kaXRpb24xX3Byb2IpKSArCiAgICAgIGdncmFzdHI6Omdlb21fcG9pbnRfcmFzdChzaXplPTAuMSwgZHBpPTcwMCkgKwogICAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICAKICB9CiAgICB9KQoKdW1hcF9scwpgYGAKYGBge3J9CnBvcHMgPC0gc2NhbigiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL3BvcF9zYW1wbGVfMl9jbGVhbi50eHQiLCB3aGF0PSIiKQp1bWFwX2xzIDwtIGxhcHBseShwb3BzLCBmdW5jdGlvbihwKXsKICBmaWxlbmFtZSA8LSBwYXN0ZTAoJy9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS9iZW5jaG1hcmtfZW1icnlvX3BvcF8nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9yZXBsYWNlKHAsICIgIiwgIl8iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnX2VucjAuOV9zZWVkNDUuY29sZGF0YS5jc3YnKQogIGlmIChmaWxlLmV4aXN0cyhmaWxlbmFtZSkpewogICAgY29sZGF0YSA8LSByZWFkX2NzdihmaWxlbmFtZSkKICAgIGNvbERhdGEoZW1icnlvX3NjZSkgPC0gY29sdW1uX3RvX3Jvd25hbWVzKGNvbGRhdGEpICU+JSBEYXRhRnJhbWUoKQogICAgZGF0YS5mcmFtZShyZWR1Y2VkRGltKGVtYnJ5b19zY2UsICdVTUFQJykpICU+JQogICAgICBkcGx5cjo6cmVuYW1lKFVNQVAxPVgxLCBVTUFQMj1YMikgJT4lCiAgICAgIG11dGF0ZShDb25kaXRpb24xX3Byb2I9ZW1icnlvX3NjZSRDb25kaXRpb24xX3Byb2IgPiAwLjYpICU+JQogICAgICBnZ3Bsb3QoYWVzKFVNQVAxLCBVTUFQMiwgY29sb3I9Q29uZGl0aW9uMV9wcm9iKSkgKwogICAgICBnZ3Jhc3RyOjpnZW9tX3BvaW50X3Jhc3Qoc2l6ZT0wLjEsIGRwaT03MDApICsKICAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkgKwogICAgICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDE2KSAgCiAgfQogICAgfSkKCnVtYXBfbHMKYGBgCgoKIyMgUGljayB0aHJlc2hvbGQgZm9yIGNlbGxzIGluIHRydWUgREEgcmVnaW9ucyBiYXNlZCBvbiBwKEMxKSBkaXN0cmlidXRpb24KClJlYWQgZnVsbCBvdXRjb21lcyBhbmQgdHJ1ZSBwcm9iYWJpbGl0aWVzCgpgYGB7cn0KcmVhZDRfcHJvYl9oaXN0IDwtIGZ1bmN0aW9uKGRhdGFfaWQpewogIG91dGRpciA8LSBnbHVlKCIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsve2RhdGFfaWR9LyIpCiAgcmVzX2ZpbGVzIDwtIGxpc3QuZmlsZXMob3V0ZGlyLCBwYXR0ZXJuPWdsdWUoIntkYXRhX2lkfS4rYmF0Y2hFZmZlY3QwLkRBcmVzdWx0cyIpKQogIHJlc19maWxlc19mdWxsIDwtIGxpc3QuZmlsZXMob3V0ZGlyLCBwYXR0ZXJuPWdsdWUoIntkYXRhX2lkfS4rYmF0Y2hFZmZlY3QwLkRBcmVzdWx0cyIpLCBmdWxsLm5hbWVzID0gVFJVRSkKICByZXNfZmlsZXNfZnVsbF9ub21lbGQgPC0gc3RyX3N1YnNldChyZXNfZmlsZXNfZnVsbCwgIm1lbGR8Y3lkYXJfYmF0Y2h8bG91dmFpbl9iYXRjaHxtaWxvX2JhdGNoIiwgbmVnYXRlID0gVFJVRSkKICAKICByZXNfbHMgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbF9ub21lbGQpLCBmdW5jdGlvbihpKXsgCiAgICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgICBiZW5jaG1hcmtfZGYgPC0gcmVhZF9jc3YocmVzX2ZpbGVzX2Z1bGxfbm9tZWxkW2ldKSAKICAgICMjIENoZWNrIGlmIGNvbmRpdGlvbnMgd2VyZSBzd2FwcGVkIGluIHRlc3QKICAgIHByZWRfY29yIDwtIGJlbmNobWFya19kZiAlPiUKICAgICAgbXV0YXRlKHByZWQ9ZmFjdG9yKHByZWQsIGxldmVscz1jKCJOZWdMRkMiLCAiTm90REEiLCAiUG9zTEZDIiksIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgICAgIG11dGF0ZShwcmVkPWFzLm51bWVyaWMocHJlZCkpICU+JQogICAgICBzdW1tYXJpc2UoY29yKHByZWQsIHRydWVfcHJvYikpCiAgICAjIyBTd2FwIG91dGNvbWVzIGlmIHNvCiAgICBpZiAoIWlzLm5hKHByZWRfY29yKSkgewogICAgICBpZiAocHJlZF9jb3IgPCAtIDAuMSkgewogICAgICAgIGJlbmNobWFya19kZiA8LSBtdXRhdGUoYmVuY2htYXJrX2RmLCBwcmVkID0gaWZlbHNlKHByZWQ9PSJOZWdMRkMiLCAiUG9zTEZDIiwgaWZlbHNlKHByZWQ9PSJQb3NMRkMiLCAiTmVnTEZDIiwgIk5vdERBIikpKQogICAgICB9CiAgICB9CiAgICBiZW5jaG1hcmtfZGYgJT4lCiAgICAgIG11dGF0ZShpZD1pKQogICAgfSkKICAKICByZXNfZGYgPC0gcmVzX2xzICAlPiUKICAgIHB1cnJyOjpyZWR1Y2UoYmluZF9yb3dzKSAKICAjICU+JQogICMgICBzZWxlY3QodHJ1ZV9wcm9iLCBwcmVkLCBtZXRob2QpIAogIAogIHJldHVybihyZXNfZGYpICAKfQoKY2x1c3Rlcl9yZXNfZGYgPC0gcmVhZDRfcHJvYl9oaXN0KCJjbHVzdGVyM3giKQpsaW5lYXJfcmVzX2RmIDwtIHJlYWQ0X3Byb2JfaGlzdCgibGluZWFyM3giKQpicmFuY2hfcmVzX2RmIDwtIHJlYWQ0X3Byb2JfaGlzdCgiYnJhbmNoaW5nM3giKQplbWJyeW9fcmVzX2RmIDwtIHJlYWQ0X3Byb2JfaGlzdCgiZW1icnlvIikKYGBgCgpQbG90IGRpc3RyaWJ1dGlvbiBvZiBQKEMxKSBpbiBjZWxscyBpZGVudGlmaWVkIGFzIERBIGJ5IGRpZmZlcmVudCBtZXRob2RzCgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTh9CmNhbGN1bGF0ZV9xdWFudGlsZV90aHJlc2ggPC0gZnVuY3Rpb24ocmVzX2RmKXsKICByZXR1cm4ocXVhbnRpbGUoMS1yZXNfZGZbcmVzX2RmJG1ldGhvZD09Im1pbG8iLF1bWyJ0cnVlX3Byb2IiXV0sIHByb2JzID0gc2VxKDAsMSwgYnk9MC4yNSkpWyI3NSUiXSkKfQoKcGxvdF9wX2hpc3QgPC0gZnVuY3Rpb24ocmVzX2RmKXsKICAjIyBDYWxjdWxhdGUgdGhyZXNob2xkCiAgdGhyZXNoIDwtIGNhbGN1bGF0ZV9xdWFudGlsZV90aHJlc2gocmVzX2RmKQogIAogICMjIFBsb3QgaGlzdG9ncmFtIG9mIHAoQzEpIGZvciBwcmVkaWN0ZWQgREEgY2VsbHMKICBwIDwtIHJlc19kZiAlPiUKICAgIGRwbHlyOjpmaWx0ZXIocHJlZCE9Ik5vdERBIikgJT4lCiAgICAjIG11dGF0ZShjb2xvcj1pZmVsc2UodHJ1ZV9wcm9iPT0wLjUsICIwLjUiLCIwIikpICU+JQogICAgZ2dwbG90KGFlcygxIC0gdHJ1ZV9wcm9iKSkgKwogICAgIyBnZW9tX2RlbnNpdHkoYWVzKGNvbG9yPXByZWQpKSArCiAgICBmYWNldF9ncmlkKG1ldGhvZH5wcmVkLCBzY2FsZXM9ImZyZWVfeSIsIGxhYmVsbGVyPXBsX2xhYmVsbGVyKSArCiAgICBnZW9tX2hpc3RvZ3JhbShiaW5zPTUwLCBhZXMoZmlsbD1wcmVkKSkgKwogICAgeGxhYigiUChDMSkiKSArIHlsYWIoIiMgREEgY2VsbHMiKSArCiAgICB0aGVtZV9idyhiYXNlX3NpemU9MTYpICsKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlNldDEiLCBuYW1lPSJQcmVkaWN0ZWQgZWZmZWN0IikgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gdGhyZXNoLCBsaW5ldHlwZT0yKSAKICBwCn0KCiMgcGxvdF9wX2hpc3QoY2x1c3Rlcl9yZXNfZGYpICsgZ2d0aXRsZSgiY2x1c3RlcnMiKSAKcGxvdF9wX2hpc3QobGluZWFyX3Jlc19kZikgKyBnZ3RpdGxlKCJsaW5lYXIiKSArCnBsb3RfcF9oaXN0KGJyYW5jaF9yZXNfZGYpICsgZ2d0aXRsZSgiYnJhbmNoaW5nIikgKwpwbG90X3BfaGlzdChlbWJyeW9fcmVzX2RmKSArIGdndGl0bGUoImVtYnJ5byIpICsKICBwbG90X2xheW91dChndWlkZXM9ImNvbGxlY3QiKSArCiAgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICIvcEMxX2hpc3RvZ3JhbXMucGRmIiksIHdpZHRoPTE4LCBoZWlnaHQgPSA2KQoKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MTZ9CnBsb3RfdGhyZXNoX2hpc3QgPC0gZnVuY3Rpb24oIGxpbmVhcl9yZXNfZGYpewogIHF1YW50cyA8LSBxdWFudGlsZSgxLWxpbmVhcl9yZXNfZGYkdHJ1ZV9wcm9iLCBzZXEoMCwgMSwgMC4wNSkpCiAga2VlcF9xdWFudHMgPC0gYygiMjUlIiwgIjUwJSIsICAiOTAlIiwgIjk1JSIpCiAgbGluZWFyX3Jlc19kZiAlPiUKICAgIGZpbHRlcihtZXRob2Q9PSJtaWxvIikgJT4lCiAgICAgIGdncGxvdChhZXMoMSAtIHRydWVfcHJvYikpICsKICAgICAgZ2VvbV9oaXN0b2dyYW0oYmlucz01MCkgKwogICAgICB4bGFiKCJQKEMxKSIpICsgeWxhYigiIyBjZWxscyIpICsKICAgICAgdGhlbWVfYncoYmFzZV9zaXplPTE2KSArCiAgICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IlNldDEiLCBuYW1lPSJQcmVkaWN0ZWQgZWZmZWN0IikgKwogICAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBxdWFudHNba2VlcF9xdWFudHNdLCBsaW5ldHlwZT0yKSArCiAgICBjb29yZF9jYXJ0ZXNpYW4oY2xpcCA9ICdvZmYnKSArCiAgICBhbm5vdGF0ZSgndGV4dCcsIHg9cXVhbnRzW2tlZXBfcXVhbnRzXSwgeT1JbmYsIGxhYmVsPShrZWVwX3F1YW50cyksIGhqdXN0PTAsIHZqdXN0PTAsIGFuZ2xlPTYwKSArCiAgICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBxdWFudHNbIjc1JSJdLCBsaW5ldHlwZT0yLCBjb2xvcj0icmVkIikgKwogICAgYW5ub3RhdGUoJ3RleHQnLCB4PXF1YW50c1siNzUlIl0sIHk9SW5mLCBsYWJlbD0iNzUlIiwgaGp1c3Q9MCwgdmp1c3Q9MCwgYW5nbGU9NjAsIGNvbG9yPSJyZWQiKSArCiAgICBhbm5vdGF0ZSgndGV4dCcsIHg9SW5mLCB5PUluZiwgbGFiZWw9cGFzdGUoJ3QgPScsIHJvdW5kKHF1YW50c1siNzUlIl0sIDMpKSwgaGp1c3Q9MS4xLCB2anVzdD0xLjUsIGFuZ2xlPTAsIGNvbG9yPSdyZWQnLCBzaXplPTUpICsKICAgIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDEsMC41LDEsMC41KSwgImNtIiksIHRpdGxlID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMSkpIAp9CgoocGxvdF90aHJlc2hfaGlzdChsaW5lYXJfcmVzX2RmKSArIGdndGl0bGUoIjFEIHRyYWplY3RvcnkiLCBzdWJ0aXRsZT0iIikgfApwbG90X3RocmVzaF9oaXN0KGJyYW5jaF9yZXNfZGYpICsgZ2d0aXRsZSgiQnJhbmNoaW5nIHRyYWplY3RvcnkiLCBzdWJ0aXRsZT0iIikgfApwbG90X3RocmVzaF9oaXN0KGVtYnJ5b19yZXNfZGYpICsgZ2d0aXRsZSgiTW91c2UgR2FzdHJ1bGF0aW9uIiwgc3VidGl0bGU9IiIpKSArCiAgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJwQzFfZnVsbF9oaXN0X3F1YW50aWxlcy5wZGYiKSwgd2lkdGg9MTYsIGhlaWdodCA9IDUpCmBgYAoKCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTV9CmxpbmVhcl9yZXNfZGYgJT4lCiAgZ3JvdXBfYnkoaWQpICU+JQogIG11dGF0ZShtYXhfcEMxID0gMS1taW4odHJ1ZV9wcm9iKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcihtYXhfcEMxPT0wLjcpICU+JQogIHBsb3RfcF9oaXN0KCkgKwogIHhsaW0oMC41LDEpICsKICBnZ3RpdGxlKCdtYXhfcEMxID0gMC43JykgKwoKbGluZWFyX3Jlc19kZiAlPiUKICBncm91cF9ieShpZCkgJT4lCiAgbXV0YXRlKG1heF9wQzEgPSAxLW1pbih0cnVlX3Byb2IpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKG1heF9wQzE9PTAuOCkgJT4lCiAgcGxvdF9wX2hpc3QoKSArCiAgeGxpbSgwLjUsMSkgKwogIGdndGl0bGUoJ21heF9wQzEgPSAwLjgnKSArCgpsaW5lYXJfcmVzX2RmICU+JQogIGdyb3VwX2J5KGlkKSAlPiUKICBtdXRhdGUobWF4X3BDMSA9IDEtbWluKHRydWVfcHJvYikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIobWF4X3BDMT09MC45KSAlPiUKICBwbG90X3BfaGlzdCgpICsKICB4bGltKDAuNSwxKSArCiAgZ2d0aXRsZSgnbWF4X3BDMSA9IDAuOScpICsKCnBsb3RfbGF5b3V0KGd1aWRlcz0iY29sbGVjdCIpCiAgCmBgYAoKVXNlIDc1JSBxdWFudGlsZSBvZiBQKEMxKSBpbiBhbGwgY2VsbHMgdG8gZGVmaW5lIHRocmVzaG9sZCBmb3IgdHJ1ZSBEQQoKYGBge3J9CmxpbmVhcl90aHJlc2ggPC0gY2FsY3VsYXRlX3F1YW50aWxlX3RocmVzaChsaW5lYXJfcmVzX2RmKQpicmFuY2hpbmdfdGhyZXNoIDwtIGNhbGN1bGF0ZV9xdWFudGlsZV90aHJlc2goYnJhbmNoX3Jlc19kZikKZW1icnlvX3RocmVzaCA8LSBjYWxjdWxhdGVfcXVhbnRpbGVfdGhyZXNoKGVtYnJ5b19yZXNfZGYpCmBgYAoKIyMgQmVuY2htYXJraW5nIG9uIHNpbXVsYXRlZCBkYXRhCgpEZWZpbmUgdXRpbHMKCmBgYHtyfQojIyBVdGlsIHRvIGNvbXB1dGUgYmVuY2htYXJrIG91dGNvbWUgZ2l2ZW4gYSBwcm9iYWJpbGl0eSB0aHJlc2hvbGQgZm9yIHRydWUgREEKLm91dGNvbWVfYnlfcHJvYiA8LSBmdW5jdGlvbihiZW5jaG1hcmtfZGYsIGRhX3VwcGVyKXsKICBEQV90aHJlc2ggPC0gMSAtIGRhX3VwcGVyCiAgYmVuY2htYXJrX2RmIDwtIGJlbmNobWFya19kZiAlPiUKICAgIG11dGF0ZSh0cnVlID0gaWZlbHNlKGJlbmNobWFya19kZiR0cnVlX3Byb2IgPCBEQV90aHJlc2gsICJOZWdMRkMiLCBpZmVsc2UoYmVuY2htYXJrX2RmJHRydWVfcHJvYiA+IDEtREFfdGhyZXNoLCAiUG9zTEZDIiwgIk5vdERBIikpKSAKICBpZiAoYmVuY2htYXJrX2RmJG1ldGhvZFsxXT09Im1lbGQiKSB7CiAgICBiZW5jaG1hcmtfZGYgPC0gbXV0YXRlKGJlbmNobWFya19kZiwgcHJlZCA9IGlmZWxzZShDb25kaXRpb24yIDwgREFfdGhyZXNoLCAiTmVnTEZDIiwgIk5vdERBIikpIAogIH0KICAjIyBDaGVjayBpZiBjb25kaXRpb25zIHdlcmUgc3dhcHBlZCBpbiB0ZXN0CiAgcHJlZF9jb3IgPC0gYmVuY2htYXJrX2RmICU+JQogICAgZ3JvdXBfYnkocHJlZCkgJT4lCiAgICBzdW1tYXJpc2UobT1tZWFuKHRydWVfcHJvYikpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgbXV0YXRlKHByZWQ9ZmFjdG9yKHByZWQsIGxldmVscz1jKCJOZWdMRkMiLCAiTm90REEiLCAiUG9zTEZDIiksIG9yZGVyZWQgPSBUUlVFKSkgJT4lCiAgICBtdXRhdGUocHJlZD1hcy5udW1lcmljKHByZWQpKSAlPiUKICAgIHN1bW1hcmlzZShjPWNvcihwcmVkLCBtKSkgJT4lCiAgICBwdWxsKGMpCiAgIyMgU3dhcCBvdXRjb21lcyBpZiBzbwogIGlmICghaXMubmEocHJlZF9jb3IpKSB7CiAgICBpZiAocHJlZF9jb3IgPCAwKSB7CiAgICAgIGJlbmNobWFya19kZiA8LSBtdXRhdGUoYmVuY2htYXJrX2RmLCBwcmVkID0gaWZlbHNlKHByZWQ9PSJOZWdMRkMiLCAiUG9zTEZDIiwgaWZlbHNlKHByZWQ9PSJQb3NMRkMiLCAiTmVnTEZDIiwgIk5vdERBIikpKQogICAgfQogIH0KICBjYWxjdWxhdGVfb3V0Y29tZShiZW5jaG1hcmtfZGYpCn0KCiMjIFV0aWwgdG8gcGxvdCBiZW5jaG1hcmtpbmcgcmVzdWx0cyBvbiBVTUFQCnBsb3Rfb3V0Y29tZV91bWFwIDwtIGZ1bmN0aW9uKHNjZSwgbWV0aG9kLCBwb3AsIGVuciwgc2VlZCwgYmF0Y2hFZmZlY3QsIHRydWU9RkFMU0UsIGRhdGFfaWQ9ImVtYnJ5byIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWRfZGltPSJ1bWFwX2JhdGNoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFzdGVyaXplPUZBTFNFKXsKICBjb2xkYXRhX2ZpbGUgPC0gbGlzdC5maWxlcyhpbmRpciwgcGF0dGVybj1wYXN0ZTAoIi4rIixkYXRhX2lkLCJfcG9wXyIsICBwb3AsIl9lbnIiLGVuciwiX3NlZWQiLCBzZWVkLCAiLmNvbGRhdGEuY3N2IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKQogIGNvbERhdGEoc2NlKSA8LSByZWFkX2Nzdihjb2xkYXRhX2ZpbGUpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoKSAlPiUgRGF0YUZyYW1lKCkKICAKICByZXNfZmlsZSA8LSBsaXN0LmZpbGVzKG91dGRpciwgCiAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuPSBwYXN0ZTAoIi4rIixkYXRhX2lkLCJfcG9wXyIsIHBvcCwiX2VuciIsZW5yLCJfc2VlZCIsIHNlZWQsICcuK2JhdGNoRWZmZWN0JyxiYXRjaEVmZmVjdCwiLkRBcmVzdWx0cy4iLG1ldGhvZCwiLmNzdiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lcyA9IFRSVUUpCiAgaWYgKG1ldGhvZD09Im1lbGQiKSB7CiAgICBzY2UkcHJlZGljdGVkIDwtIGlmZWxzZShyZWFkX2NzdihyZXNfZmlsZSlbWyJDb25kaXRpb24yIl1dIDwgMC4zLCAiTmVnTEZDIiwgJ05vdERBJykgIAogIH0gZWxzZSBpZiAobWV0aG9kPT0iZGFzZXEiKSB7CiAgICBzY2UkcHJlZGljdGVkIDwtIGlmZWxzZShyZWFkX2NzdihyZXNfZmlsZSlbWyJwcmVkIl1dID09ICJOZWdMRkMiLCAnUG9zTEZDJywgaWZlbHNlKHJlYWRfY3N2KHJlc19maWxlKVtbInByZWQiXV0gPT0gIlBvc0xGQyIsICJOZWdMRkMiLCAiTm90REEiKSkKICB9IGVsc2UgewogICAgc2NlJHByZWRpY3RlZCA8LSByZWFkX2NzdihyZXNfZmlsZSlbWyJwcmVkIl1dCiAgfQogIGlmICh0cnVlKSB7CiAgICBwbCA8LSBkYXRhLmZyYW1lKHJlZHVjZWREaW0oc2NlLCByZWRfZGltKSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lX2FsbCggfiBjKCJVTUFQMSIsICJVTUFQMiIpICkgJT4lCiAgICBtdXRhdGUodHJ1ZT1zY2UkQ29uZGl0aW9uMV9wcm9iKSAlPiUKICAgIGFycmFuZ2UodHJ1ZSkgJT4lCiAgICBnZ3Bsb3QoYWVzKFVNQVAxLCBVTUFQMiwgY29sb3I9dHJ1ZSkpICsgCiAgICBnZW9tX3BvaW50KHNpemU9MC4xKSArCiAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhuYW1lPSJDMSBwcm9iYWJpbGl0eSIsIGxpbWl0cz1jKDAuNSwwLjkpKSArCiAgICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemU9MTgpICsKICAgICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2NvbG9yYmFyKHRpdGxlLnBvc2l0aW9uPSJ0b3AiLCB0aXRsZS5oanVzdCA9IDAuNSkpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpIAogIH0gZWxzZSB7CiAgICBwbCA8LSBkYXRhLmZyYW1lKHJlZHVjZWREaW0oc2NlLCByZWRfZGltKSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lX2FsbCggfiBjKCJVTUFQMSIsICJVTUFQMiIpICkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKG1ldGhvZD1tZXRob2QpICU+JQogICAgZHBseXI6Om11dGF0ZShwcmVkaWN0ZWQ9ZmFjdG9yKHNjZSRwcmVkaWN0ZWQsIGxldmVscz1jKCJOZWdMRkMiLCAiUG9zTEZDIiwgJ05vdERBJykpKSAlPiUKICAgIGRwbHlyOjphcnJhbmdlKC0gcHJlZGljdGVkKSAlPiUKICAgIGdncGxvdChhZXMoVU1BUDEsIFVNQVAyLCBjb2xvcj1wcmVkaWN0ZWQpKSArIAogICAgZ2VvbV9wb2ludChzaXplPTAuMSkgKwogICAgZ2VvbV9wb2ludChkYXRhPSAuICU+JSBmaWx0ZXIocHJlZGljdGVkIT0iTm90REEiKSwgc2l6ZT0wLjIpICsKICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoTmVnTEZDPSJyZWQiLCBOb3REQT0iZ3JleSIsIFBvc0xGQz0iYmx1ZSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoTmVnTEZDPSJFbnJpY2hlZCBpbiBDMSIsIE5vdERBPSJObyBEQSIsIFBvc0xGQz0iRGVwbGV0ZWQgaW4gQzEiKSwgbmFtZT0nJykgKwogICAgIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9MSkpKSArCiAgICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemU9MTgpICsKICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249YyguMTUsLjIpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICAgICAgZmFjZXRfd3JhcChtZXRob2R+LikgIAogIH0KICBpZiAocmFzdGVyaXplKSB7CiAgICBwbCA8LSBwbCArIHJhc3Rlcml6ZShnZW9tX3BvaW50KHNpemU9MC4xKSwgZHBpID0gMzAwKQogIH0KICBwbAp9CgojIyBDb252ZXJ0IGNvbmRpdGlvbiBwcm9iYWJpbGl0eSB0byBMRkMKcHJvYjJGQyA8LSBmdW5jdGlvbihwcm9iKXsKICBsb2coKHByb2IpLygxIC0gcHJvYikpCn0KYGBgCgojIyMjIExpbmVhciAtIDFEIHRyYWplY3RvcnkKCmBgYHtyfQpvdXRkaXIgPC0gIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9saW5lYXIzeC8iCnJlc19maWxlcyA8LSBsaXN0LmZpbGVzKG91dGRpciwgcGF0dGVybj0ibGluZWFyLitEQXJlc3VsdHMiKQpyZXNfZmlsZXNfZnVsbCA8LSBsaXN0LmZpbGVzKG91dGRpciwgcGF0dGVybj0ibGluZWFyM3guK0RBcmVzdWx0cyIsIGZ1bGwubmFtZXMgPSBUUlVFKQppbl9maWxlcyA8LSBsaXN0LmZpbGVzKCJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvIiwgcGF0dGVybj0ibGluZWFyM3guK2NvbGRhdGEuY3N2IikKCiMjIE1ha2UgZGF0YSBmcmFtZSB3IGJlbmNobWFyayBwYXJhbWV0ZXJzCmxpbmVhcl9vdXRfbWV0YV9kZiA8LSBkYXRhLmZyYW1lKGZpbGVfaWQgPSBzdHJfcmVtb3ZlX2FsbChyZXNfZmlsZXMsICJiZW5jaG1hcmtfZW1icnlvX3BvcF98LmNzdiIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCAiYmF0Y2hFZmZlY3QiKSkgJT4lCiAgbXV0YXRlKHNlZWQ9c3RyX3JlbW92ZShzZWVkLCAic2VlZCIpLCBiYXRjaEVmZmVjdD1zdHJfcmVtb3ZlKGJhdGNoRWZmZWN0LCAiYmF0Y2hFZmZlY3QiKSkgCgojIyBMb2FkIHJlc3VsdHMKbGluZWFyX291dGNvbWVfZGYgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbCksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2ldKSAlPiUKICAgICAgLm91dGNvbWVfYnlfcHJvYihkYV91cHBlciA9IGxpbmVhcl90aHJlc2gpICU+JQogICAgICBtdXRhdGUoREFfdGhyZXNoPWxpbmVhcl90aHJlc2gpICU+JQogICAgICB1bmdyb3VwKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoLSBtZXRob2QpICU+JQogICAgICBiaW5kX2NvbHMobGluZWFyX291dF9tZXRhX2RmW2ksXSkgCiAgcG9wX2VuciA8LSBhcy5udW1lcmljKGxpbmVhcl9vdXRfbWV0YV9kZltpLCJlbnIiXSkKICBiZW5jaG1hcmtfZGYKICB9KSAlPiUKICBwdXJycjo6cmVkdWNlKGJpbmRfcm93cykgJT4lCiAgIyMgUmVtb3ZlIE1FTEQKICBmaWx0ZXIobWV0aG9kIT0ibWVsZCIpCgpsaW5lYXJfb3V0Y29tZV9kZiAKYGBgCgpgYGB7cn0KcGxfZGYgPC0gbGluZWFyX291dGNvbWVfZGYgJT4lCiAgZmlsdGVyKG1ldGhvZCE9Im1pbG9fYmF0Y2giKSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgJT4lCiAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksCiAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgIEZEUj1pZmVsc2UoaXMubmFuKEZEUiksIDAsIEZEUiksCiAgICAgICAgIFByZWNpc2lvbj1pZmVsc2UoaXMubmFuKFByZWNpc2lvbiksIDAsIFByZWNpc2lvbikpICU+JQogIG11dGF0ZShwb3A9c3RyX3JlcGxhY2UocG9wLCAiXyIsICIgIikpICU+JQogIG11dGF0ZShwb3A9ZmFjdG9yKHBvcCwgbGV2ZWxzPXVuaXF1ZShwb3ApKSkgJT4lCiAgZmlsdGVyKERBX3RocmVzaCA+PSBsaW5lYXJfdGhyZXNoICYgYmF0Y2hFZmZlY3Q9PTApIApwbF9yaWdodCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBUUFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgZmFjZXRfZ3JpZCgufm1ldGhvZCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICAgIHRoZW1lKCNheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKcGxfbGVmdCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBGRFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlPTIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgZmFjZXRfZ3JpZCgufm1ldGhvZCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICAgIHRoZW1lKCNheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCnBsIDwtIHBsX3JpZ2h0IC8gcGxfbGVmdCArCiAgcGxvdF9sYXlvdXQoZ3VpZGVzPSdjb2xsZWN0JykgJgogICAgdGhlbWUoI2F4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKQoKcGwKCmBgYAoKCgpQbG90IFVNQVAKYGBge3IsIGZpZy53aWR0aD0xMCxmaWcuaGVpZ2h0PTR9CmxpbmVhcl9zY2UgPC0gcmVhZFJEUygifi9kYXRhL21pbG9fYmVuY2htYXJrL2xpbmVhcjN4X2RhdGFfYm0uUkRTIikKaW5kaXIgPC0gIn4vZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8iCgpuYW1lcyhyZWR1Y2VkRGltcyhsaW5lYXJfc2NlKSlbMl0gPC0gInVtYXBfYmF0Y2giCmNvbG5hbWVzKHJlZHVjZWREaW1zKGxpbmVhcl9zY2UpW1syXV0pIDwtIGMoIlgxIiwgIlgyIikgCgpwbF90b3AgPC0gcGxvdF9vdXRjb21lX3VtYXAobGluZWFyX3NjZSwgbWV0aG9kID0gJ21pbG8nLCBwb3A9Ik01IiwgZW5yID0gMC45LCBzZWVkID0gNDMsYmF0Y2hFZmZlY3QgPSAwLCB0cnVlID0gVFJVRSwgZGF0YV9pZD0ibGluZWFyM3giKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKSAKCnBsb3RfbGluZWFyIDwtICgocGxfdG9wKSB8IChwbCAmIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikpKSArCiAgcGxvdF9sYXlvdXQod2lkdGhzID0gYygwLjUsMikpCnBsb3RfbGluZWFyCmBgYAoKCiMjIyMgQnJhbmNoaW5nCgpgYGB7cn0Kb3V0ZGlyIDwtICIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvYnJhbmNoaW5nM3gvIgpyZXNfZmlsZXMgPC0gbGlzdC5maWxlcyhvdXRkaXIsIHBhdHRlcm49ImJyYW5jaGluZzN4LitEQXJlc3VsdHMiKQpyZXNfZmlsZXNfZnVsbCA8LSBsaXN0LmZpbGVzKG91dGRpciwgcGF0dGVybj0iYnJhbmNoaW5nM3guK0RBcmVzdWx0cyIsIGZ1bGwubmFtZXMgPSBUUlVFKQppbl9maWxlcyA8LSBsaXN0LmZpbGVzKCJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvIiwgcGF0dGVybj0iYnJhbmNoaW5nM3guK2NvbGRhdGEuY3N2IikKCiMjIE1ha2UgZGF0YSBmcmFtZSB3IGJlbmNobWFyayBwYXJhbWV0ZXJzCmJyYW5jaF9vdXRfbWV0YV9kZiA8LSBkYXRhLmZyYW1lKGZpbGVfaWQgPSBzdHJfcmVtb3ZlX2FsbChyZXNfZmlsZXMsICJiZW5jaG1hcmtfZW1icnlvX3BvcF98LmNzdiIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCAiYmF0Y2hFZmZlY3QiKSkgJT4lCiAgbXV0YXRlKHNlZWQ9c3RyX3JlbW92ZShzZWVkLCAic2VlZCIpLCBiYXRjaEVmZmVjdD1zdHJfcmVtb3ZlKGJhdGNoRWZmZWN0LCAiYmF0Y2hFZmZlY3QiKSkgCgojIyBMb2FkIHJlc3VsdHMKYnJhbmNoX291dGNvbWVfZGYgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbCksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2ldKSAlPiUKICAgICAgLm91dGNvbWVfYnlfcHJvYihkYV91cHBlciA9IGJyYW5jaGluZ190aHJlc2gpICU+JQogICAgICBtdXRhdGUoREFfdGhyZXNoPWJyYW5jaGluZ190aHJlc2gpICU+JQogICAgICB1bmdyb3VwKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoLSBtZXRob2QpICU+JQogICAgICBiaW5kX2NvbHMoYnJhbmNoX291dF9tZXRhX2RmW2ksXSkgCiAgcG9wX2VuciA8LSBhcy5udW1lcmljKGJyYW5jaF9vdXRfbWV0YV9kZltpLCJlbnIiXSkKICBiZW5jaG1hcmtfZGYKICB9KSAlPiUKICBwdXJycjo6cmVkdWNlKGJpbmRfcm93cykgJT4lCiAgIyMgUmVtb3ZlIE1FTEQKICBmaWx0ZXIobWV0aG9kIT0ibWVsZCIpCgpicmFuY2hfb3V0Y29tZV9kZiAKICAKYGBgCgpgYGB7cn0KcGxfZGYgPC0gYnJhbmNoX291dGNvbWVfZGYgJT4lCiAgZmlsdGVyKG1ldGhvZCE9Im1pbG9fYmF0Y2giKSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgJT4lCiAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksCiAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgIEZEUj1pZmVsc2UoaXMubmFuKEZEUiksIDAsIEZEUiksCiAgICAgICAgIFByZWNpc2lvbj1pZmVsc2UoaXMubmFuKFByZWNpc2lvbiksIDAsIFByZWNpc2lvbikpICU+JQogIG11dGF0ZShwb3A9c3RyX3JlcGxhY2UocG9wLCAiXyIsICIgIikpICU+JQogIG11dGF0ZShwb3A9ZmFjdG9yKHBvcCwgbGV2ZWxzPXVuaXF1ZShwb3ApKSkgJT4lCiAgZmlsdGVyKERBX3RocmVzaCA+PSBicmFuY2hpbmdfdGhyZXNoICYgYmF0Y2hFZmZlY3Q9PTApIApwbF9yaWdodCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBUUFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgZmFjZXRfZ3JpZCgufm1ldGhvZCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICAgIHRoZW1lKCNheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKcGxfbGVmdCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBGRFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlPTIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgZmFjZXRfZ3JpZCgufm1ldGhvZCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICB0aGVtZSgjYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpwbCA8LSBwbF9yaWdodCAvIHBsX2xlZnQgKwpwbG90X2xheW91dChndWlkZXM9J2NvbGxlY3QnKSAmCiAgICB0aGVtZSgjYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCnBsCgpgYGAKClBsb3QgVU1BUApgYGB7ciwgZmlnLmhlaWdodD04LGZpZy53aWR0aD02fQpicmFuY2hfc2NlIDwtIHJlYWRSRFMoIn4vZGF0YS9taWxvX2JlbmNobWFyay9icmFuY2hpbmczeF9kYXRhX2JtLlJEUyIpCmluZGlyIDwtICJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvIgoKbmFtZXMocmVkdWNlZERpbXMoYnJhbmNoX3NjZSkpWzJdIDwtICJ1bWFwX2JhdGNoIgpjb2xuYW1lcyhyZWR1Y2VkRGltcyhicmFuY2hfc2NlKVtbMl1dKSA8LSBjKCJYMSIsICJYMiIpIAoKcGxfdG9wIDwtIHBsb3Rfb3V0Y29tZV91bWFwKGJyYW5jaF9zY2UsIG1ldGhvZCA9ICdtaWxvJywgcG9wPSJNNSIsIGVuciA9IDAuOSwgc2VlZCA9IDQzLGJhdGNoRWZmZWN0ID0gMCwgdHJ1ZSA9IFRSVUUsIGRhdGFfaWQ9ImJyYW5jaGluZzN4IikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikgCgpwbG90X2JyYW5jaCA8LSAoKHBsX3RvcCkgfCAocGwgJiB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIpKSkgKwogIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMC41LDIpKQpwbG90X2JyYW5jaApgYGAKCgojIyMjIFNpbXBsZSBjbHVzdGVyaW5nCgpgYGB7cn0Kb3V0ZGlyIDwtICIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvY2x1c3RlcjN4LyIKcmVzX2ZpbGVzIDwtIGxpc3QuZmlsZXMob3V0ZGlyLCBwYXR0ZXJuPSJjbHVzdGVyM3guK0RBcmVzdWx0cyIpCnJlc19maWxlc19mdWxsIDwtIGxpc3QuZmlsZXMob3V0ZGlyLCBwYXR0ZXJuPSJjbHVzdGVyM3guK0RBcmVzdWx0cyIsIGZ1bGwubmFtZXMgPSBUUlVFKQppbl9maWxlcyA8LSBsaXN0LmZpbGVzKCJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvIiwgcGF0dGVybj0iY2x1c3RlcjN4Litjb2xkYXRhLmNzdiIpCgojIyBNYWtlIGRhdGEgZnJhbWUgdyBiZW5jaG1hcmsgcGFyYW1ldGVycwpjbHVzdGVyX291dF9tZXRhX2RmIDwtIGRhdGEuZnJhbWUoZmlsZV9pZCA9IHN0cl9yZW1vdmVfYWxsKHJlc19maWxlcywgImJlbmNobWFya19lbWJyeW9fcG9wX3wuY3N2IikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICIuREFyZXN1bHRzLiIsIGludG89YygiZmlsZV9pZCIsICJtZXRob2QiKSkgJT4lCiAgc2VwYXJhdGUoY29sID0gZmlsZV9pZCwgc2VwID0gIl9lbnIiLCBpbnRvPWMoInBvcCIsICJmaWxlX2lkIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfIiwgaW50bz1jKCJlbnIiLCAic2VlZCIsICJiYXRjaEVmZmVjdCIpKSAlPiUKICBtdXRhdGUoc2VlZD1zdHJfcmVtb3ZlKHNlZWQsICJzZWVkIiksIGJhdGNoRWZmZWN0PXN0cl9yZW1vdmUoYmF0Y2hFZmZlY3QsICJiYXRjaEVmZmVjdCIpKSAKCiMjIExvYWQgcmVzdWx0cwpjbHVzdGVyX291dGNvbWVfZGYgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbCksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2ldKSAlPiUKICAgICAgLm91dGNvbWVfYnlfcHJvYihkYV91cHBlciA9IDAuNTUpICU+JQogICAgICBtdXRhdGUoREFfdGhyZXNoPTAuNTUpICU+JQogICAgICB1bmdyb3VwKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoLSBtZXRob2QpICU+JQogICAgICBiaW5kX2NvbHMoY2x1c3Rlcl9vdXRfbWV0YV9kZltpLF0pIAogIHBvcF9lbnIgPC0gYXMubnVtZXJpYyhjbHVzdGVyX291dF9tZXRhX2RmW2ksImVuciJdKQogIGJlbmNobWFya19kZgogIH0pICU+JQogIHB1cnJyOjpyZWR1Y2UoYmluZF9yb3dzKSAlPiUKICAjIyBSZW1vdmUgTUVMRAogIGZpbHRlcihtZXRob2QhPSJtZWxkIikKCmNsdXN0ZXJfb3V0Y29tZV9kZiAKICAKYGBgCgpgYGB7cn0KcGxfZGYgPC0gY2x1c3Rlcl9vdXRjb21lX2RmICU+JQogZmlsdGVyKG1ldGhvZCE9Im1pbG9fYmF0Y2giKSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgJT4lCiAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksCiAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgIEZEUj1pZmVsc2UoaXMubmFuKEZEUiksIDAsIEZEUiksCiAgICAgICAgIFByZWNpc2lvbj1pZmVsc2UoaXMubmFuKFByZWNpc2lvbiksIDAsIFByZWNpc2lvbikpICU+JQogIG11dGF0ZShwb3A9c3RyX3JlcGxhY2UocG9wLCAiXyIsICIgIikpICU+JQogIG11dGF0ZShwb3A9ZmFjdG9yKHBvcCwgbGV2ZWxzPXVuaXF1ZShwb3ApKSkgJT4lCiAgZmlsdGVyKERBX3RocmVzaCA+PSAwLjU1ICYgYmF0Y2hFZmZlY3Q9PTApIApwbF9yaWdodCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBUUFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgZmFjZXRfZ3JpZCgufm1ldGhvZCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICB0aGVtZSgjYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCnBsX2xlZnQgPC0gcGxfZGYgJT4lCiAgZ2dwbG90KGFlcyhhcy5mYWN0b3Iocm91bmQocHJvYjJGQyhhcy5udW1lcmljKGVucikpLDEpKSwgRkRSLCBjb2xvcj1tZXRob2QpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuYWxwaGEgPSAwKSArCiAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbShhbHBoYT0wLjUsIHBvc2l0aW9uPSJzdGFjayIsIHNpemU9MC41KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4xLCBsaW5ldHlwZT0yKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTYpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbWV0aG9kX2NvbG9ycywgbGFiZWxzPXNldE5hbWVzKG1ldGhvZF9sYWJlbHMsIG1ldGhvZF9uYW1lcykpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIGZhY2V0X2dyaWQoLn5tZXRob2QsIGxhYmVsbGVyPXBsX2xhYmVsbGVyKSArCiAgdGhlbWUoI2F4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICAgICkKCnBsIDwtIHBsX3JpZ2h0IC8gcGxfbGVmdCArCnBsb3RfbGF5b3V0KGd1aWRlcz0nY29sbGVjdCcpICYKICB0aGVtZSgjYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpCiAgICAgICAgKQpwbApgYGAKUGxvdCBVTUFQCmBgYHtyLCBmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTEwfQpjbHVzdGVyX3NjZSA8LSByZWFkUkRTKCJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvY2x1c3RlcjN4X2RhdGFfYm0uUkRTIikKaW5kaXIgPC0gIn4vZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8iCgpuYW1lcyhyZWR1Y2VkRGltcyhjbHVzdGVyX3NjZSkpWzJdIDwtICJ1bWFwX2JhdGNoIgpjb2xuYW1lcyhyZWR1Y2VkRGltcyhjbHVzdGVyX3NjZSlbWzJdXSkgPC0gYygiWDEiLCAiWDIiKSAKcGxfdG9wIDwtIHBsb3Rfb3V0Y29tZV91bWFwKGNsdXN0ZXJfc2NlLCBtZXRob2QgPSAnbWlsbycsIHBvcD0iQjMiLCBlbnIgPSAwLjksIHNlZWQgPSA0MyxiYXRjaEVmZmVjdCA9IDAsIHRydWUgPSBUUlVFLCBkYXRhX2lkPSJjbHVzdGVyM3giKSArIAogdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKSAKCnBsb3RfY2x1c3RlciA8LSAoKHBsX3RvcCkgfCAocGwgJiB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIpKSkgKwogIHBsb3RfbGF5b3V0KHdpZHRocyA9IGMoMC41LDIpKQpwbG90X2NsdXN0ZXIKYGBgCgpBc3NlbWJsZSBmaWd1cmUKCmBgYHtyLCBmaWcuaGVpZ2h0PTEzLCBmaWcud2lkdGg9MTJ9CmZpZyA8LSAoCiAgIChwbG90X2NsdXN0ZXIgKSAvCiAgIChwbG90X2xpbmVhciAmIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKSAvCiAgIChwbG90X2JyYW5jaCAmIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpKQogICApICsgCiAgcGxvdF9sYXlvdXQoKSAmCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTExKSkKCmZpZyArCiAgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJzaW1EYXRhX2ZpZ3VyZS5wbmciKSwgd2lkdGg9MTAsIGhlaWdodCA9IDEzKSArCiAgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJzaW1EYXRhX2ZpZ3VyZS5wZGYiKSwgd2lkdGg9MTAsIGhlaWdodCA9IDEzKQpgYGAKCkNoZWNrIHNvbWUgZXhhbXBsZXMgCgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9Cm91dGRpciA8LSAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2NsdXN0ZXIzeC8iCmxpbmVhcl9zY2UgPC0gcmVhZFJEUygifi9kYXRhL21pbG9fYmVuY2htYXJrL2NsdXN0ZXIzeF9kYXRhX2JtLlJEUyIpCmluZGlyIDwtICJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvIgoKbmFtZXMocmVkdWNlZERpbXMobGluZWFyX3NjZSkpWzJdIDwtICJ1bWFwX2JhdGNoIgpjb2xuYW1lcyhyZWR1Y2VkRGltcyhsaW5lYXJfc2NlKVtbMl1dKSA8LSBjKCJYMSIsICJYMiIpIApwbG90X291dGNvbWVfdW1hcChzY2UgPSBsaW5lYXJfc2NlLCBtZXRob2Q9ImxvdXZhaW4iLCBwb3A9IkIzIiwgZW5yPTAuOSwgc2VlZD00MywgYmF0Y2hFZmZlY3QgPSAnMCcsIGRhdGFfaWQgPSAiY2x1c3RlcjN4IiwgdHJ1ZT1GQUxTRSkgKwpwbG90X291dGNvbWVfdW1hcChzY2UgPSBsaW5lYXJfc2NlLCBtZXRob2Q9ImN5ZGFyIiwgICBwb3A9IkIzIiwgZW5yPTAuOSwgc2VlZD00MywgYmF0Y2hFZmZlY3QgPSAnMCcsIGRhdGFfaWQgPSAiY2x1c3RlcjN4IiwgdHJ1ZT1GQUxTRSkgKwpwbG90X291dGNvbWVfdW1hcChzY2UgPSBsaW5lYXJfc2NlLCBtZXRob2Q9Im1pbG8iLCAgICBwb3A9IkIzIiwgZW5yPTAuOSwgc2VlZD00MywgYmF0Y2hFZmZlY3QgPSAnMCcsIGRhdGFfaWQgPSAiY2x1c3RlcjN4IiwgdHJ1ZT1GQUxTRSkgKwpwbG90X291dGNvbWVfdW1hcChzY2UgPSBsaW5lYXJfc2NlLCBtZXRob2Q9ImRhc2VxIiwgICBwb3A9IkIzIiwgZW5yPTAuOSwgc2VlZD00MywgYmF0Y2hFZmZlY3QgPSAnMCcsIGRhdGFfaWQgPSAiY2x1c3RlcjN4IiwgdHJ1ZT1GQUxTRSkgKwpwbG90X291dGNvbWVfdW1hcChzY2UgPSBsaW5lYXJfc2NlLCBtZXRob2Q9ImRhc2VxIiwgcG9wPSJCMyIsIGVucj0wLjksIHNlZWQ9NDMsIGJhdGNoRWZmZWN0ID0gJzAnLCBkYXRhX2lkID0gImNsdXN0ZXIzeCIsIHRydWU9VFJVRSkgKwogIHBsb3RfbGF5b3V0KGd1aWRlcz0iY29sbGVjdCIpCgpgYGAKCiMjIE1FTEQgLyBNaWxvIGNvbXBhcmlzb24KQ29tcGFyaW5nIGFjY3VyYWN5IGFuZCBwcmVjaXNpb24gb2YgdGhlIGZvbGQtY2hhbmdlIGVzdGltYXRlcyBvZiB0aGUgdHdvIG1ldGhvZHMgcnVubmluZyBNRUxEIGFuZCBNaWxvIG9uIHRoZSBzYW1lIHNpbXVsYXRpb24gb24gdGhlIGVtYnJ5byBkYXRhLgoKV2UgZXN0aW1hdGUgTEZDcyBmb3IgYm90aCBtZXRob2RzIChzZWUgYHJ1bl9taWxvVlNtZWxkLlJgKSBhbmQgY29tcGFyZSB3aXRoIHRoZSB0cnVlIExGQwoKYGBge3J9CiMjIE1lYW4gc3F1YXJlZCBlcnJvcgpNU0UgPC0gZnVuY3Rpb24odHJ1ZSwgcHJlZCl7CiAgbWVhbigodHJ1ZSAtIHByZWQpXjIpCn0KCiMjIE1lYW4gYmlhcyBlcnJvcgpNQkUgPC0gZnVuY3Rpb24odHJ1ZSwgcHJlZCl7CiAgbWVhbih0cnVlIC0gcHJlZCkKfQoKIyMgTWVhbiBhYnMgZXJyb3IKTUFFIDwtIGZ1bmN0aW9uKHRydWUsIHByZWQpewogIG1lYW4oYWJzKHRydWUgLSBwcmVkKSkKfQoKIyMgc3RkIGVycm9yClNFIDwtIGZ1bmN0aW9uKHRydWUsIHByZWQpewogIHNxcnQoKHN1bSgodHJ1ZSAtIHByZWQpXjIpKS8obGVuZ3RoKHByZWQpIC0gMikpCn0KCiMjIENvbnZlcnQgY29uZGl0aW9uIHByb2JhYmlsaXR5IHRvIExGQwpwcm9iMkZDIDwtIGZ1bmN0aW9uKHByb2IpewogIGxvZygocHJvYikvKDEgLSBwcm9iKSkKfQoKbGZjX2NvbXBhcmlzb24gPC0gZnVuY3Rpb24obWlsb19vdXQsIG1lbGRfb3V0KXsKICAjICMjIEFubm90YXRlIG5ob29kcyB0aGF0IG92ZXJsYXAgdHJ1ZSBEQSBjZWxscwogICMgbWlsb19vdXQkREFyZXMgPC0gYW5ub3RhdGVOaG9vZHMobWlsb19vdXQkTWlsbywgbWlsb19vdXQkREFyZXMsIGNvbGRhdGFfY29sID0gInRydWVfbGFiZWxzIikKICAKICAjIyBUYWtlIHByb2JhYmlsaXR5IGVzdGltYXRlIGF0IG5ob29kIGluZGljZXMgCiAgIyMgKHRha2luZyB0aGUgYXZnIG9mIGNlbGxzIGluIHRoZSBuaG9vZCBnaXZlcyBlcXVpdmFsZW50IHJlc3VsdHMpCiAgIyBuaF9tZWxkIDwtIG1lbGRfb3V0W3VubGlzdChuaG9vZEluZGV4KG1pbG9fb3V0JE1pbG8pKSxdCiAgbmhfbWVsZCA8LSBtZWxkX291dFttaWxvX291dCRuaG9vZEluZGV4LF0KICAKICAjIyBDb252ZXJ0IHByb2JhYmlsaXRpZXMgdG8gTEZDICAKICBsZmNfZGYgPC0gbmhfbWVsZCAlPiUKICAgICAgICBtdXRhdGUobWlsb19MRkM9bWlsb19vdXQkbG9nRkMsCiAgICAgICAgIG1pbG9fc2lnbmlmPW1pbG9fb3V0JFNwYXRpYWxGRFIgPCAwLjEsCiAgICAgICAgICMgdHJ1ZV9sYWJlbHM9bWlsb19vdXQkdHJ1ZV9sYWJlbHMsCiAgICAgICAgIHRydWVfbGFiZWxzPWlmZWxzZSh0cnVlX3Byb2IgPCAxLWVtYnJ5b190aHJlc2gsICJOZWdMRkMiLCAiTm90REEiKSwKICAgICAgICAgbmhfc2l6ZT1taWxvX291dCRuaF9zaXplCiAgICAgICAgICkgJT4lCiAgICAgICAgbXV0YXRlKHRydWVfTEZDPXByb2IyRkModHJ1ZV9wcm9iKSwgbWVsZF9MRkM9cHJvYjJGQyhDb25kaXRpb24yKSkgJT4lCiAgICAgICAgc2VsZWN0KC0gbWV0aG9kLCAtIHRydWVfcHJvYiwgLSBDb25kaXRpb24yKSAlPiUKICAgIHBpdm90X2xvbmdlcihjb2xzPWMobWlsb19MRkMsIG1lbGRfTEZDKSwgbmFtZXNfdG89Im1ldGhvZCIsIHZhbHVlc190bz0iZXN0aW1hdGVkX0xGQyIpCiAgICAKICBsZmNfZGYKICB9CgojIyBMb2FkIHJlc3VsdHMgZnJvbSBydW5fbWlsb1ZTbWVsZC5SCmRhdGFfZGlyIDwtICcvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvTUVMRHZzTWlsby8nCm1pbG9fZmlsZXMgPC0gbGlzdC5maWxlcyhkYXRhX2RpciwgcGF0dGVybj0ibWlsby4rY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpCm1pbG9fcmVzX291dHMgPC0gbGFwcGx5KG1pbG9fZmlsZXMsIHJlYWRfY3N2KQoKbWVsZF9maWxlcyA8LSBzdHJfcmVtb3ZlX2FsbChtaWxvX2ZpbGVzLCBwYXN0ZTAoZGF0YV9kaXIsICIvIikpICU+JQogIHN0cl9yZXBsYWNlKCJtaWxvIiwgIm1lbGQiKSAlPiUKICBwYXN0ZTAoZGF0YV9kaXIsIC4pCm1lbGRfb3V0cyA8LSBsYXBwbHkobWVsZF9maWxlcywgcmVhZF9jc3YpCgoKbWVsZFZTbWlsb19tZXRhIDwtIGRhdGEuZnJhbWUoZmlsZV9pZCA9IHN0cl9yZW1vdmVfYWxsKG1lbGRfZmlsZXMsIHBhc3RlMChkYXRhX2RpciwgInwvfGJlbmNobWFya19lbWJyeW9fcG9wX3wuY3N2IikpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCAiYmF0Y2hFZmZlY3QiKSkgJT4lCiAgc2VwYXJhdGUoY29sID0gbWV0aG9kLCBzZXAgPSAiXFwuIiwgaW50bz1jKCJtZXRob2QiLCAnaycpKSAlPiUKICBtdXRhdGUoc2VlZD1zdHJfcmVtb3ZlKHNlZWQsICJzZWVkIiksIAogICAgICAgICBrPWFzLm51bWVyaWMoc3RyX3JlbW92ZShrLCAiayIpKSwgCiAgICAgICAgIGJhdGNoRWZmZWN0PXN0cl9yZW1vdmUoYmF0Y2hFZmZlY3QsICJiYXRjaEVmZmVjdCIpLAogICAgICAgICApICU+JQogIHNlbGVjdCgtIG1ldGhvZCkKICAKbGZjX2RmIDwtIGxhcHBseShzZXFfYWxvbmcobWlsb19yZXNfb3V0cyksIGZ1bmN0aW9uKGkpIGxmY19jb21wYXJpc29uKG1pbG9fcmVzX291dHNbW2ldXSwgbWVsZF9vdXRzW1tpXV0pICU+JQogICAgICAgICAgICAgICAgICAgYmluZF9jb2xzKG1lbGRWU21pbG9fbWV0YVtpLF0pKSAlPiUKICBwdXJycjo6cmVkdWNlKGJpbmRfcm93cykKCgpgYGAKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CnBsX2xhYmVsbGVyIDwtIGxhYmVsbGVyKAogIGVuciA9IGVucl9sYWJlbGxlcjIsCiAgdHJ1ZV9sYWJlbHMgPSBsYWJlbF92YWx1ZSwKICBwb3AgPSBsYWJlbF92YWx1ZSwKICAuZGVmYXVsdCA9IGxhYmVsX2JvdGgKKQoKcGxfbWlsbyA8LSBsZmNfZGYgJT4lIAogIGZpbHRlcihwb3AgJWluJSBjKCJHdXQiLCAiRXJ5dGhyb2lkMSIsICJTb21pdGljX21lc29kZXJtIikpICU+JQogIGZpbHRlcihtZXRob2Q9PSJtaWxvX0xGQyIgJiBiYXRjaEVmZmVjdD09JzAnKSAlPiUKICBncm91cF9ieShlbnIsIHRydWVfbGFiZWxzLCBwb3AsIGspICU+JQogIG11dGF0ZShNQUUgPSBNQUUodHJ1ZV9MRkMsIGVzdGltYXRlZF9MRkMpKSAlPiUKICBnZ3Bsb3QoYWVzKHRydWVfTEZDLCBlc3RpbWF0ZWRfTEZDKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MC42LCBhZXMoY29sb3I9dHJ1ZV9sYWJlbHMpKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9MikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlPTIpICsKICBnZW9tX2FibGluZShsaW5ldHlwZT0yKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKE5lZ0xGQz0icmVkIiwgTm90REE9ImdyZXkiKSwgbGFiZWxzPWMoTmVnTEZDPSJOZWdMRkMiLCBOb3REQT0ibm8gREEiKSwgbmFtZT0nJykgKwogIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gYyhzaXplPTIpKSkgKwogIGZhY2V0X2dyaWQocG9wfmVuciwgbGFiZWxsZXIgPSBwbF9sYWJlbGxlcikgKwogIHhsYWIoIlRydWUgTEZDIikgKyB5bGFiKCJNaWxvIGVzdGltYXRlZCBMRkMiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpCgpwbF9tZWxkIDwtIGxmY19kZiAlPiUgCiAgZmlsdGVyKHBvcCAlaW4lIGMoIkd1dCIsICJFcnl0aHJvaWQxIiwgIlNvbWl0aWNfbWVzb2Rlcm0iKSkgJT4lCiAgZmlsdGVyKG1ldGhvZD09Im1lbGRfTEZDIiAmIGJhdGNoRWZmZWN0PT0nMCcpICU+JQogICMgZmlsdGVyKGVucj09MC45ICYgaz09NTAgJiB0cnVlX2xhYmVscz09Ik5lZ0xGQyIpCiAgZ3JvdXBfYnkoZW5yLCB0cnVlX2xhYmVscywgcG9wLCBrKSAlPiUKICBtdXRhdGUoTUFFID0gTUFFKHRydWVfTEZDLCBlc3RpbWF0ZWRfTEZDKSkgJT4lCiAgZ2dwbG90KGFlcyh0cnVlX0xGQywgZXN0aW1hdGVkX0xGQykpICsgCiAgZ2VvbV9wb2ludChzaXplPTAuNiwgYWVzKGNvbG9yPXRydWVfbGFiZWxzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPTIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0yKSArCiAgZ2VvbV9hYmxpbmUobGluZXR5cGU9MikgKwogIHhsYWIoIlRydWUgTEZDIikgKyB5bGFiKCJNRUxEIGVzdGltYXRlZCBMRkMiKSArCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBjKHNpemU9MikpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKE5lZ0xGQz0icmVkIiwgTm90REE9ImdyZXkiKSwgbGFiZWxzPWMoTmVnTEZDPSJOZWdMRkMiLCBOb3REQT0ibm8gREEiKSwgbmFtZT0iIikgKwogIGZhY2V0X2dyaWQocG9wfmVuciwgbGFiZWxsZXIgPSBwbF9sYWJlbGxlcikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQoKcGxfbGVmdCA8LSAocGxfbWlsbyB8IHBsX21lbGQpICsgCiAgcGxvdF9sYXlvdXQoZ3VpZGVzPSJjb2xsZWN0IikgJgogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIiwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSkpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9MTJ9CgpwbF9taWxvIDwtIGxmY19kZiAlPiUgCiAgZmlsdGVyKHBvcCAlaW4lIGMoIkd1dCIsICJFcnl0aHJvaWQxIiwgIlNvbWl0aWNfbWVzb2Rlcm0iKSkgJT4lCiAgZmlsdGVyKG1ldGhvZD09Im1pbG9fTEZDIiAmIGJhdGNoRWZmZWN0PT0nMC41JykgJT4lCiAgZ3JvdXBfYnkoZW5yLCB0cnVlX2xhYmVscywgcG9wLCBrKSAlPiUKICBtdXRhdGUoTUFFID0gTUFFKHRydWVfTEZDLCBlc3RpbWF0ZWRfTEZDKSkgJT4lCiAgZ2dwbG90KGFlcyh0cnVlX0xGQywgZXN0aW1hdGVkX0xGQykpICsgCiAgZ2VvbV9wb2ludChzaXplPTAuNiwgYWVzKGNvbG9yPXRydWVfbGFiZWxzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPTIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0yKSArCiAgZ2VvbV9hYmxpbmUobGluZXR5cGU9MikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhOZWdMRkM9InJlZCIsIE5vdERBPSJncmV5IiksIGxhYmVscz1jKE5lZ0xGQz0iTmVnTEZDIiwgTm90REE9Im5vIERBIiksIG5hbWU9JycpICsKICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGMoc2l6ZT0yKSkpICsKICBmYWNldF9ncmlkKHBvcH5lbnIsIGxhYmVsbGVyID0gcGxfbGFiZWxsZXIpICsKICB4bGFiKCJUcnVlIExGQyIpICsgeWxhYigiTWlsbyBlc3RpbWF0ZWQgTEZDIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQoKcGxfbWVsZCA8LSBsZmNfZGYgJT4lIAogIGZpbHRlcihwb3AgJWluJSBjKCJHdXQiLCAiRXJ5dGhyb2lkMSIsICJTb21pdGljX21lc29kZXJtIikpICU+JQogIGZpbHRlcihtZXRob2Q9PSJtZWxkX0xGQyIgJiBiYXRjaEVmZmVjdD09JzAuNScpICU+JQogICMgZmlsdGVyKGVucj09MC45ICYgaz09NTAgJiB0cnVlX2xhYmVscz09Ik5lZ0xGQyIpCiAgZ3JvdXBfYnkoZW5yLCB0cnVlX2xhYmVscywgcG9wLCBrKSAlPiUKICBtdXRhdGUoTUFFID0gTUFFKHRydWVfTEZDLCBlc3RpbWF0ZWRfTEZDKSkgJT4lCiAgZ2dwbG90KGFlcyh0cnVlX0xGQywgZXN0aW1hdGVkX0xGQykpICsgCiAgZ2VvbV9wb2ludChzaXplPTAuNiwgYWVzKGNvbG9yPXRydWVfbGFiZWxzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPTIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0yKSArCiAgZ2VvbV9hYmxpbmUobGluZXR5cGU9MikgKwogIHhsYWIoIlRydWUgTEZDIikgKyB5bGFiKCJNRUxEIGVzdGltYXRlZCBMRkMiKSArCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBjKHNpemU9MikpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKE5lZ0xGQz0icmVkIiwgTm90REE9ImdyZXkiKSwgbGFiZWxzPWMoTmVnTEZDPSJOZWdMRkMiLCBOb3REQT0ibm8gREEiKSwgbmFtZT0iIikgKwogIGZhY2V0X2dyaWQocG9wfmVuciwgbGFiZWxsZXIgPSBwbF9sYWJlbGxlcikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0KQoKCnBsX2xlZnRfYmUgPC0gKHBsX21pbG8gfCBwbF9tZWxkKSArIAogIHBsb3RfbGF5b3V0KGd1aWRlcz0iY29sbGVjdCIpICYKICB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIsIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLDEpKQpgYGAKCmBgYHtyfQpwbF9yaWdodDEgPC0gbGZjX2RmICU+JQogIGZpbHRlcihrPT01MCkgJT4lCiAgZ3JvdXBfYnkobWV0aG9kLCBwb3AsIHRydWVfbGFiZWxzLCBrLCBlbnIsIGJhdGNoRWZmZWN0KSAlPiUKICBzdW1tYXJpc2UoTVNFID0gTVNFKHRydWVfTEZDLCBlc3RpbWF0ZWRfTEZDKSwgc2Q9c2QoYWJzKHRydWVfTEZDIC0gZXN0aW1hdGVkX0xGQykpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKG1ldGhvZCA9IHN0cl9yZW1vdmUobWV0aG9kLCJfTEZDIikpICU+JQogIGRwbHlyOjpyZW5hbWUoYEJhdGNoIGVmZmVjdCBcbm1hZ25pdHVkZWAgPSBiYXRjaEVmZmVjdCkgJT4lCiAgZmlsdGVyKHRydWVfbGFiZWxzPT0iTm90REEiKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksIDEpKSwgTVNFLCBjb2xvciA9IG1ldGhvZCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZmFjZXRfZ3JpZCh0cnVlX2xhYmVsc35gQmF0Y2ggZWZmZWN0IFxubWFnbml0dWRlYCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICB0aGVtZV9idyhiYXNlX3NpemU9MTgpICsKICB4bGFiKCJTaW11bGF0ZWQgbG9nLUZvbGQgQ2hhbmdlIikgKwogIHNjYWxlX2NvbG9yX21ldGhvZHMoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwxKSkgKwogIHlsaW0oMCwwLjYpCnBsX3JpZ2h0MiA8LSBsZmNfZGYgJT4lCiAgZmlsdGVyKGs9PTUwKSAlPiUKICBncm91cF9ieShtZXRob2QsIHBvcCwgdHJ1ZV9sYWJlbHMsIGssIGVuciwgYmF0Y2hFZmZlY3QpICU+JQogIHN1bW1hcmlzZShNU0UgPSBNU0UodHJ1ZV9MRkMsIGVzdGltYXRlZF9MRkMpLCBzZD1zZChhYnModHJ1ZV9MRkMgLSBlc3RpbWF0ZWRfTEZDKSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUobWV0aG9kID0gc3RyX3JlbW92ZShtZXRob2QsIl9MRkMiKSkgJT4lCiAgZHBseXI6OnJlbmFtZShgQmF0Y2ggZWZmZWN0IFxubWFnbml0dWRlYCA9IGJhdGNoRWZmZWN0KSAlPiUKICBmaWx0ZXIodHJ1ZV9sYWJlbHM9PSJOZWdMRkMiKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksIDEpKSwgTVNFLCBjb2xvciA9IG1ldGhvZCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZmFjZXRfZ3JpZCh0cnVlX2xhYmVsc35gQmF0Y2ggZWZmZWN0IFxubWFnbml0dWRlYCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICB0aGVtZV9idyhiYXNlX3NpemU9MTgpICsKICB4bGFiKCJTaW11bGF0ZWQgbG9nLUZvbGQgQ2hhbmdlIikgKwogIHNjYWxlX2NvbG9yX21ldGhvZHMoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwxKSkgKwogIHlsaW0oMCwwLjYpCgpwbF9yaWdodCA8LSBwbF9yaWdodDEgKyBwbF9yaWdodDIgKwogIHBsb3RfbGF5b3V0KGd1aWRlcz0iY29sbGVjdCIpICYKICB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIsIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygxLDEpKSAKCnBsX3JpZ2h0CmBgYAoKYGBge3IsIGZpZy53aWR0aD0xNCwgZmlnLmhlaWdodD0xMH0KKHBsX2xlZnQgL3BsX2xlZnRfYmUgLyAgcGxfcmlnaHQpICsKICBwbG90X2xheW91dChoZWlnaHRzPWMoMS41LCAxLjUsIDEpKSArCiAgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIpICsKICAjIGdnc2F2ZSgifi9tb3VudC9nZHJpdmUvbWlsby9GaWd1cmVzL2JlbmNobWFya192Mi9TRmlnX01FTER2c01pbG8ucGRmIiwgd2lkdGggPSAxNSwgaGVpZ2h0ID0gMTYpICsKICBnZ3NhdmUoIn4vbW91bnQvZ2RyaXZlL21pbG8vRmlndXJlcy9yZXN1Ym1pc3Npb24vc3VwcGxlbWVudGFyeS9zdXBwbF9maWdfbWVsZFZTbWlsby5wZGYiLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSAxOSkgCiAgZ2dzYXZlKCJ+L21vdW50L2dkcml2ZS9taWxvL0ZpZ3VyZXMvYmVuY2htYXJrX3YyL1NGaWdfTUVMRHZzTWlsby5wbmciLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSAxNikKYGBgCgoKCiMjIEVtYnJ5byBkYXRhCgojIyMgVy9vIGJhdGNoIGVmZmVjdAoKYGBge3J9CiMjIFJlYWQgb3V0cHV0cwpvdXRkaXIgPC0gIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9lbWJyeW8vIgpyZXNfZmlsZXMgPC0gbGlzdC5maWxlcyhvdXRkaXIsIHBhdHRlcm49Ii5EQXJlc3VsdHMiKQpyZXNfZmlsZXNfZnVsbCA8LSBsaXN0LmZpbGVzKG91dGRpciwgcGF0dGVybj0iLkRBcmVzdWx0cyIsIGZ1bGwubmFtZXMgPSBUUlVFKQojIGluX2ZpbGVzIDwtIGxpc3QuZmlsZXMoIn4vZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8iLCBwYXR0ZXJuPSJjb2xkYXRhLmNzdiIpCgojIyBNYWtlIGRhdGEgZnJhbWUgdyBiZW5jaG1hcmsgcGFyYW1ldGVycwpvdXRfbWV0YV9kZiA8LSBkYXRhLmZyYW1lKGZpbGVfaWQgPSBzdHJfcmVtb3ZlX2FsbChyZXNfZmlsZXMsICJiZW5jaG1hcmtfZW1icnlvX3BvcF98LmNzdiIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCAiYmF0Y2hFZmZlY3QiKSkgJT4lCiAgbXV0YXRlKHNlZWQ9c3RyX3JlbW92ZShzZWVkLCAic2VlZCIpLCBiYXRjaEVmZmVjdD1zdHJfcmVtb3ZlX2FsbChiYXRjaEVmZmVjdCwgImJhdGNoRWZmZWN0IikpIAoKIyMgUmVhZCBiZW5jaG1hcmsgcmVzdWx0cyB3L28gYmF0Y2ggZWZmZWN0cwpub19iYXRjaF9maWxlcyA8LSBzdHJfZGV0ZWN0KHJlc19maWxlc19mdWxsLCAiYmF0Y2hFZmZlY3QwLkRBcmVzdWx0IikgJiAhc3RyX2RldGVjdChyZXNfZmlsZXNfZnVsbCwgImxvdXZhaW5fYmF0Y2h8Y3lkYXJfYmF0Y2h8bWlsb19iYXRjaCIpCiMgcHJvYl90aHJlc2hfdmVjIDwtIHNlcSgwLjUsIDAuOSwgMC4wNSkKb3V0Y29tZV9kZiA8LSBsYXBwbHkoc2VxX2Fsb25nKHJlc19maWxlc19mdWxsW25vX2JhdGNoX2ZpbGVzXSksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW25vX2JhdGNoX2ZpbGVzXVtpXSkKICBwb3BfZW5yIDwtIGFzLm51bWVyaWMob3V0X21ldGFfZGZbbm9fYmF0Y2hfZmlsZXMsXVtpLCJlbnIiXSkKICBiZW5jaG1hcmtfZGYgJT4lCiAgICAgIC5vdXRjb21lX2J5X3Byb2IoZGFfdXBwZXIgPSBlbWJyeW9fdGhyZXNoKSAlPiUKICAgICAgbXV0YXRlKERBX3RocmVzaD1lbWJyeW9fdGhyZXNoKSAlPiUKICAgICAgdW5ncm91cCgpICU+JQogICAgICBkcGx5cjo6c2VsZWN0KC0gbWV0aG9kKSAlPiUKICAgICAgYmluZF9jb2xzKG91dF9tZXRhX2RmW25vX2JhdGNoX2ZpbGVzLF1baSxdKSAlPiUKICAgICAgZmlsdGVyKERBX3RocmVzaCA8IGFzLm51bWVyaWMoZW5yKSkKfSkgJT4lCiAgcHVycnI6OnJlZHVjZShiaW5kX3Jvd3MpCgp3cml0ZV9jc3Yob3V0Y29tZV9kZiwgIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9vdXRjb21lX2VtYnJ5b192M19ub0JhdGNoLmNzdiIpCmBgYAoKClJlYWQgb3V0Y29tZSBmb3IgZW1icnlvIChidWlsdCB3aXRoIHdyYXBwZXIgYGJ1aWxkX291dGNvbWUuUmApCgpgYGB7cn0Kb3V0Y29tZV9kZiA8LSByZWFkX2NzdigiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL291dGNvbWVfZW1icnlvX3YzX25vQmF0Y2guY3N2IikKYGBgCgpgYGB7cn0Kb3V0Y29tZV9kZiA8LSBvdXRjb21lX2RmICU+JQogIGZpbHRlcihEQV90aHJlc2g9PWVtYnJ5b190aHJlc2gpICU+JQogIGZpbHRlcihwb3AhPSJNaXhlZF9tZXNvZGVybSIpCgpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTV9CiMgZW5yX2xhYmVsbGVyMiA8LSBmdW5jdGlvbih2YXJpYWJsZSwgdmFsdWUsIHNwbGl0X2xpbmVzPUZBTFNFKXsKIyAgIGZjIDwtIHJvdW5kKHByb2IyRkMoYXMubnVtZXJpYyh2YWx1ZSkpLCAyKQojICAgZW5yX25hbWUgPC0gcGFzdGUoImxvZ0ZDID0gIiwgZmMpCiMgICByZXR1cm4oZW5yX25hbWUpCiMgfQoKcGxfZGYgPC0gb3V0Y29tZV9kZiAlPiUgCiAgIGZpbHRlcihiYXRjaEVmZmVjdD09MCAmIHN0cl9kZXRlY3QobWV0aG9kLCAiX2JhdGNoIiwgbmVnYXRlID0gVFJVRSkpICU+JSAKICAgbXV0YXRlKEZEUiA9IEZQLyhUUCtGUCkpICU+JSAKICAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksIAogICAgICAgICAgRlBSPWlmZWxzZShpcy5uYW4oRlBSKSwgMCwgRlBSKSwgCiAgICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLCAKICAgICAgICAgIFByZWNpc2lvbj1pZmVsc2UoaXMubmFuKFByZWNpc2lvbiksIDAsIFByZWNpc2lvbikpICU+JSAKICAgZmlsdGVyKERBX3RocmVzaCA+PSBlbWJyeW9fdGhyZXNoICYgYmF0Y2hFZmZlY3Q9PTApICAlPiUgCiAgIG11dGF0ZShlbnI9YXMuY2hhcmFjdGVyKGVucikpICAKCnBfdG9wIDwtIHBsX2RmICU+JQogIGZpbHRlcihiYXRjaEVmZmVjdD09IjAiKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBUUFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICAjIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuMSwgbGluZXR5cGU9MikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0aG9kX2NvbG9ycywgbGFiZWxzPXNldE5hbWVzKG1ldGhvZF9sYWJlbHMsIG1ldGhvZF9uYW1lcykpICsKICBmYWNldF9ncmlkKC5+bWV0aG9kLCBsYWJlbGxlcj1wbF9sYWJlbGxlcikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKCnBfYm90dG9tIDwtIHBsX2RmICU+JQogIGZpbHRlcihiYXRjaEVmZmVjdD09IjAiKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihyb3VuZChwcm9iMkZDKGFzLm51bWVyaWMoZW5yKSksMSkpLCBGRFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlPTIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgZmFjZXRfZ3JpZCgufm1ldGhvZCwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICB4bGFiKCdTaW11bGF0ZWQgbG9nLUZvbGQgQ2hhbmdlJykgCgoocF90b3AgLyBwX2JvdHRvbSkgKyBwbG90X2xheW91dChndWlkZXM9ImNvbGxlY3QiKSArCiAgZ2dzYXZlKCJ+L21vdW50L2dkcml2ZS9taWxvL0ZpZ3VyZXMvYmVuY2htYXJrX3YyL2JtX25vYmF0Y2gucGRmIiwgIHdpZHRoID0gMTEsIGhlaWdodCA9IDYpICsKICBnZ3NhdmUoIn4vbW91bnQvZ2RyaXZlL21pbG8vRmlndXJlcy9iZW5jaG1hcmtfdjIvYm1fbm9iYXRjaC5wbmciLCAgd2lkdGggPSAxMSwgaGVpZ2h0ID0gNikKCmBgYAoKCiMjIyMgSW1wYWN0IG9mIHBvcHVsYXRpb24gc2l6ZQoKUmFuZ2Ugb2Ygc2l6ZXMKYGBge3J9Cm11dGF0ZShvdXRjb21lX2RmLCBuREE9IFRQK0ZOKSAlPiUKICBmaWx0ZXIobWV0aG9kPT0ibWlsbyIgJiBiYXRjaEVmZmVjdD09IjAiKSAlPiUKICBzdW1tYXJpc2UobWluKG5EQSkpCiAgZ2dwbG90KGFlcyhuREEsVFBSKSkgKwogIGdlb21fcG9pbnQoKQpgYGAKCkdlbmVyYXRlIGxhYmVscyAKCi0gQ2hhbmdpbmcgbG9naXQgcGFyYW06IHRvIGhhdmUgYmlnZ2VyIERBIHJlZ2lvbiBhcm91bmQgdGhlIHNhbWUgY2VudHJvaWQKLSBjYXBwaW5nIHRoZSBlbnJpY2htZW50LCBzbyB0byBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBEQSBjZWxscyB3aXRoIGRpZmZlcmVudCBmb2xkIGNoYW5nZXMKCkkgcGljayBfRXJ5dGhyb2lkMl8gYW5kIF9DYXVkYWxfbmV1cmVjdG9kZXJtXyBhcyB0aGUgYmVzdCBhbmQgd29yc2UgcGVyZm9ybWFuY2UgcmVnaW9ucwoKYGBge3IsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD00fQpzYXZlX2xhYmVsc19jYXBwZWQgPC0gZnVuY3Rpb24oc2NlLCBjYXBfZW5yLCBwb3AsIHNlZWQsIGFfbG9naXQpewogIGlmIChzdHJfZGV0ZWN0KHBvcCwgIl8iKSkgewogICAgcG9wIDwtIHN0cl9yZXBsYWNlKHBvcCwgIl8iLCAiICIpCiAgfQogIHNjZSA8LSBhZGRfc3ludGhldGljX2xhYmVsc19wb3Aoc2NlLCBwb3A9cG9wLCBwb3BfY29sdW1uID0gImNlbGx0eXBlIiwgc2VlZD1zZWVkLCBwb3BfZW5yPTAuOSwgY2FwX2VuciA9IGNhcF9lbnIsYV9sb2dpdCA9ICBhX2xvZ2l0KQogIHRydWVfbGFiZWxzIDwtIGlmZWxzZShzY2UkQ29uZGl0aW9uMV9wcm9iIDwgKDEtY2FwX2VuciksICJOZWdMRkMiLCBpZmVsc2Uoc2NlJENvbmRpdGlvbjJfcHJvYiA+IGNhcF9lbnIsICJQb3NMRkMiLCAiTm90REEiKSkKICBjb2xEYXRhKHNjZSlbWyJ0cnVlX2xhYmVscyJdXSA8LSB0cnVlX2xhYmVscwogIGlmIChzdHJfZGV0ZWN0KHBvcCwgIiAiKSkgewogICAgcG9wIDwtIHN0cl9yZXBsYWNlKHBvcCwgIiAiLCAiXyIpCiAgfQogIAogICMjIFNhdmUgY29sZGF0YQogIG91dGRpciA8LScvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvJwogIGEgPC0gc3RyX3JlbW92ZShhcy5jaGFyYWN0ZXIoYV9sb2dpdCksICJcXC4iKQogIG91dHByZWZpeCA8LSBzdHJfYygiYmVuY2htYXJrX2VtYnJ5b19wb3BfIiwgcG9wLCAnX2VucicsIGNhcF9lbnIsICJfc2VlZCIsIHNlZWQsICJfY2FwcGVkX2xvZ2l0IiwgYSkKICBjb2xkYXRhIDwtIGRhdGEuZnJhbWUoY29sRGF0YShzY2UpKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCkKICB3cml0ZV9jc3YoY29sZGF0YSwgc3RyX2Mob3V0ZGlyLCBvdXRwcmVmaXgsICIuY29sZGF0YS5jc3YiKSkKICB9CgoKc2NlIDwtIGVtYnJ5b19zY2UKIyMgRXhjbHVkZSBtaXhlZCBtZXNvZGVybSAoaXQncyB0b28gbWl4ZWQpCnBvcHMgPC0gYygiRXJ5dGhyb2lkMiIsICJDYXVkYWxfbmV1cmVjdG9kZXJtIikKCmZvciAocCBpbiBwb3BzKSB7CiAgZm9yIChlIGluIHNlcSgwLjc1LDAuOTUsIGJ5PTAuMSkgKSB7CiAgICBmb3IgKHMgaW4gYyg0Myw0NCw0NSkgKSB7CiAgICAgIGZvciAoYSBpbiBjKDAuMywwLjUsIDAuNykgKSB7CiAgICAgIHNhdmVfbGFiZWxzX2NhcHBlZChlbWJyeW9fc2NlLCBlLCBwLCBzLCBhKQogICAgICB9CiAgICB9CiAgfQp9CmBgYAoKSSBydW4gdGhlIGJlbmNobWFyayB3aXRoIHN5bnRoZXRpYyBsYWJlbHMgZ2VuZXJhdGVkIGFib3ZlIChzZWUgYHN1Ym1pdF9iZW5jaG1hcmtfY2FwcGVkLnNoYCkKClJlYWQgYWxsIHJlc3VsdHMKCmBgYHtyfQpvdXRkaXIgPC0gIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9jYXBwZWRfbG9naXQvIgpyZXNfZmlsZXMgPC0gbGlzdC5maWxlcyhvdXRkaXIsIHBhdHRlcm49Ii4rREFyZXN1bHRzLisuY3N2IikKcmVzX2ZpbGVzX2Z1bGwgPC0gbGlzdC5maWxlcyhvdXRkaXIsIHBhdHRlcm49Ii4rREFyZXN1bHRzLisuY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpCiMgaW5fZmlsZXMgPC0gbGlzdC5maWxlcygifi9kYXRhL21pbG9fYmVuY2htYXJrL3N5bnRoZXRpY19kYXRhLyIsIHBhdHRlcm49Il9lbnIwLls3OF0uK2NvbGRhdGEuY3N2IikKCiMjIE1ha2UgZGF0YSBmcmFtZSB3IGJlbmNobWFyayBwYXJhbWV0ZXJzCmNhcHBlZF9vdXRfbWV0YV9kZiA8LSBkYXRhLmZyYW1lKGZpbGVfaWQgPSBzdHJfcmVtb3ZlX2FsbChyZXNfZmlsZXMsICJiZW5jaG1hcmtfZW1icnlvX3BvcF98LmNzdiIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCdjYXBwZWQnLCdsb2dpdCcsICJiYXRjaEVmZmVjdCIpKSAlPiUKICBtdXRhdGUoc2VlZD1zdHJfcmVtb3ZlKHNlZWQsICJzZWVkIiksIGJhdGNoRWZmZWN0PXN0cl9yZW1vdmUoYmF0Y2hFZmZlY3QsICJiYXRjaEVmZmVjdCIpLAogICAgICAgICBsb2dpdD1zdHJfcmVtb3ZlKGxvZ2l0LCAibG9naXQiKSkgCgojIyBMb2FkIHJlc3VsdHMKY2FwcGVkX291dGNvbWVfZGYgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbCksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2ldKSAlPiUKICAgICAgLm91dGNvbWVfYnlfcHJvYihkYV91cHBlciA9IGVtYnJ5b190aHJlc2gpICU+JQogICAgICBtdXRhdGUoREFfdGhyZXNoPWVtYnJ5b190aHJlc2gpICU+JQogICAgICB1bmdyb3VwKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoLSBtZXRob2QpICU+JQogICAgICBiaW5kX2NvbHMoY2FwcGVkX291dF9tZXRhX2RmW2ksXSkgCiAgcG9wX2VuciA8LSBhcy5udW1lcmljKGNhcHBlZF9vdXRfbWV0YV9kZltpLCJlbnIiXSkKICBiZW5jaG1hcmtfZGYKICB9KSAlPiUKICBwdXJycjo6cmVkdWNlKGJpbmRfcm93cykKCm91dGNvbWVfZGZfcG9wc2l6ZSA8LSBjYXBwZWRfb3V0Y29tZV9kZgpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTEyfQojIyBFeHRyYWN0IG51bWJlciBvZiBEQSBjZWxscyBwZXIgc2ltdWxhdGlvbgpjb2xkYXRhX2ZpbGVzIDwtIGxpc3QuZmlsZXMoIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8iLCBwYXR0ZXJuPSJlbWJyeW8uK2NhcHBlZF9sb2dpdC4rLmNvbGRhdGEuY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpIApEQV9wb3Bfc2l6ZSA8LSBzYXBwbHkoY29sZGF0YV9maWxlcywgZnVuY3Rpb24oeCkgcmVhZF9jc3YoeCkgJT4lIHB1bGwoQ29uZGl0aW9uMV9wcm9iKSAlPiUge3N1bSguID4gZW1icnlvX3RocmVzaCl9KQpEQV9wb3Bfc2l6ZV9kZiA8LSAKICBjb2xkYXRhX2ZpbGVzICU+JSAKICBzdHJfcmVtb3ZlKCcvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvL2JlbmNobWFya19lbWJyeW9fcG9wXycpICU+JQogIHN0cl9zcGxpdCgiX2Vucnxfc2VlZHxfY2FwcGVkXyIpICU+JQogIHB1cnJyOjpyZWR1Y2UocmJpbmQpICU+JQogIGRhdGEuZnJhbWUoKSAlPiUKICBkcGx5cjo6cmVuYW1lKHBvcD1YMSwgZW5yPVgyLCBzZWVkPVgzLCBsb2dpdD1YNCkgJT4lCiAgbXV0YXRlKGxvZ2l0PXN0cl9yZW1vdmVfYWxsKGxvZ2l0LCAibG9naXR8LmNvbGRhdGEuKyIpKSAlPiUKICBtdXRhdGUocG9wX3NpemU9REFfcG9wX3NpemUpICU+JQogIGRpc3RpbmN0KCkKCiMjIE1lcmdlIHdpdGggYmVuY2htYXJrIG91dGNvbWVzCnBsX2RmIDwtIG91dGNvbWVfZGZfcG9wc2l6ZSAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdChtZXRob2QsICJfYmF0Y2giLCBuZWdhdGUgPSBUUlVFKSkgJT4lCiAgbXV0YXRlKEZEUiA9IEZQLyhUUCtGUCkpICU+JQogIG11dGF0ZShUUFI9aWZlbHNlKGlzLm5hbihUUFIpLCAwLCBUUFIpLAogICAgICAgICBGUFI9aWZlbHNlKGlzLm5hbihGUFIpLCAwLCBGUFIpLAogICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLAogICAgICAgICBQcmVjaXNpb249aWZlbHNlKGlzLm5hbihQcmVjaXNpb24pLCAwLCBQcmVjaXNpb24pKSAlPiUKICAjIG11dGF0ZShwb3A9c3RyX3JlcGxhY2UocG9wLCAiXyIsICIgIikpICU+JQogIGxlZnRfam9pbihEQV9wb3Bfc2l6ZV9kZikgJT4lCiAgYXJyYW5nZShwb3Bfc2l6ZSkgJT4lCiAgbXV0YXRlKHBvcD1mYWN0b3IocG9wLCBsZXZlbHM9dW5pcXVlKHBvcCkpKSAlPiUKICBtdXRhdGUoZW5yPWFzLmNoYXJhY3RlcihlbnIpKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9OX0KcDEgPC0gcGxfZGYgJT4lCiAgZmlsdGVyKHBvcD09IkVyeXRocm9pZDIiKSAlPiUKICBnZ3Bsb3QoYWVzKHBvcF9zaXplLCBUUFIsIGNvbG9yPW1ldGhvZCkpICsgCiAgIyBnZW9tX2JveHBsb3QoYWxwaGE9MC43LCBhZXMoY29sb3I9bWV0aG9kKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZmFjZXRfZ3JpZChlbnJ+bWV0aG9kLCBzY2FsZXM9ImZyZWVfeCIsIGxhYmVsbGVyPXBsX2xhYmVsbGVyKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArCiAgc2NhbGVfY29sb3JfbWV0aG9kcygpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgICsKICB4bGFiKCJTaXplIG9mIERBIHBvcHVsYXRpb24iKSArCiAgZ2d0aXRsZSgiRXJ5dGhyb2lkMiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSwgdmp1c3Q9MSkpCgpwMiA8LSBwbF9kZiAlPiUKICBmaWx0ZXIocG9wPT0iQ2F1ZGFsX25ldXJlY3RvZGVybSIpICU+JQogIGdncGxvdChhZXMocG9wX3NpemUsIFRQUiwgY29sb3I9bWV0aG9kKSkgKyAKICAjIGdlb21fYm94cGxvdChhbHBoYT0wLjcsIGFlcyhjb2xvcj1tZXRob2QpKSArCiAgZ2VvbV9wb2ludCgpICsKICBmYWNldF9ncmlkKGVucn5tZXRob2QsIHNjYWxlcz0iZnJlZV94IiwgbGFiZWxsZXI9cGxfbGFiZWxsZXIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfYygpICsKICBzY2FsZV9jb2xvcl9tZXRob2RzKCkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSAgKwogIHhsYWIoIlNpemUgb2YgREEgcG9wdWxhdGlvbiIpICsKICBnZ3RpdGxlKCJDYXVkYWxfbmV1cmVjdG9kZXJtIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xLCB2anVzdD0xKSkKCnAxICsgcDIgKyBwbG90X2xheW91dChndWlkZXM9J2NvbGxlY3QnKSArCiAgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIpICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwgIlNGaWdfcG9wX3NpemVzX2NhcHBlZC5wZGYiKSwgaGVpZ2h0ID0gNywgd2lkdGggPSAxNCkgKwogIGdnc2F2ZShwYXN0ZTAoZmlnZGlyLCAiU0ZpZ19wb3Bfc2l6ZXNfY2FwcGVkLnBuZyIpLCBoZWlnaHQgPSA3LCB3aWR0aCA9IDE0KQpgYGAKCiMjIyMgRXhwbGFpbiB2YXJpYWJpbGl0eSBpbiBwZXJmb3JtYW5jZSBhY3Jvc3MgZGlmZmVyZW50IHBvcHVsYXRpb25zCgpEdWUgdG8gbG93IHNpZ25hbCB0byBub2lzZSByYXRpbyBmb3IgY2VydGFpbiBzaW11bGF0aW9ucwoKCmBgYHtyfQojIyBSZWFkIGJlbmNobWFyayByZXN1bHRzIHcvbyBiYXRjaCBlZmZlY3RzIGFuZCBzZWxlY3RpbmcganVzdCB0b3AgYW5kIGJvdHRvbSBwb3B1bGF0aW9uCmtlZXBfcG9wcyA8LSBjKCJFcnl0aHJvaWQyIiwgIkNhdWRhbF9uZXVyZWN0b2Rlcm0iKQprZWVwX2ZpbGVzIDwtIHN0cl9kZXRlY3QocmVzX2ZpbGVzX2Z1bGwsICJiYXRjaEVmZmVjdDAuREFyZXN1bHQiKSAmIAogICFzdHJfZGV0ZWN0KHJlc19maWxlc19mdWxsLCAibG91dmFpbl9iYXRjaHxjeWRhcl9iYXRjaHxtaWxvX2JhdGNoIikgJgogIHN0cl9kZXRlY3QocmVzX2ZpbGVzX2Z1bGwsIHBhc3RlMChrZWVwX3BvcHMsIGNvbGxhcHNlID0gInwiKSkKCnN1cHByZXNzV2FybmluZ3MoewogIG91dGNvbWVfZGZfMiA8LSBsYXBwbHkoc2VxX2Fsb25nKHJlc19maWxlc19mdWxsW2tlZXBfZmlsZXNdKSwgZnVuY3Rpb24oaSl7IAogICAgcHJpbnQocGFzdGUoIk91dGNvbWUgbm8uICIsIGkpKQogICAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2tlZXBfZmlsZXNdW2ldKQogICAgcG9wX2VuciA8LSBhcy5udW1lcmljKG91dF9tZXRhX2RmW2tlZXBfZmlsZXMsXVtpLCJlbnIiXSkKICAgIGJlbmNobWFya19kZiA8LSBiZW5jaG1hcmtfZGYgJT4lCiAgICAgIG11dGF0ZSh0cnVlID0gaWZlbHNlKGJlbmNobWFya19kZiR0cnVlX3Byb2IgPCAxLWVtYnJ5b190aHJlc2gsICJOZWdMRkMiLCBpZmVsc2UoYmVuY2htYXJrX2RmJHRydWVfcHJvYiA+IGVtYnJ5b190aHJlc2gsICJQb3NMRkMiLCAiTm90REEiKSkpIAogICAgCiAgICAjIyBDaGVjayBpZiBjb25kaXRpb25zIHdlcmUgc3dhcHBlZCBpbiB0ZXN0CiAgICBwcmVkX2NvciA8LSBiZW5jaG1hcmtfZGYgJT4lCiAgICAgIGdyb3VwX2J5KHByZWQpICU+JQogICAgICBzdW1tYXJpc2UobT1tZWFuKHRydWVfcHJvYikpICU+JQogICAgICB1bmdyb3VwKCkgJT4lCiAgICAgIG11dGF0ZShwcmVkPWZhY3RvcihwcmVkLCBsZXZlbHM9YygiTmVnTEZDIiwgIk5vdERBIiwgIlBvc0xGQyIpLCBvcmRlcmVkID0gVFJVRSkpICU+JQogICAgICBtdXRhdGUocHJlZD1hcy5udW1lcmljKHByZWQpKSAlPiUKICAgICAgc3VtbWFyaXNlKGM9Y29yKHByZWQsIG0pKSAlPiUKICAgICAgcHVsbChjKQogICAgIyMgU3dhcCBvdXRjb21lcyBpZiBzbwogICAgaWYgKCFpcy5uYShwcmVkX2NvcikpIHsKICAgICAgaWYgKHByZWRfY29yIDwgMCkgewogICAgICAgIGJlbmNobWFya19kZiA8LSBtdXRhdGUoYmVuY2htYXJrX2RmLCBwcmVkID0gaWZlbHNlKHByZWQ9PSJOZWdMRkMiLCAiUG9zTEZDIiwgaWZlbHNlKHByZWQ9PSJQb3NMRkMiLCAiTmVnTEZDIiwgIk5vdERBIikpKQogICAgICB9CiAgICB9CiAgIAogICAgYmVuY2htYXJrX2RmICU+JQogICAgICBtdXRhdGUocHJvYl9iaW5zPWN1dCgxLXRydWVfcHJvYiwgYnJlYWtzID0gc2VxKDAuMywgMSwgYnk9MC4wNSksIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwgcmlnaHQ9RkFMU0UpKSAlPiUKICAgICAgICBncm91cF9ieShwcm9iX2JpbnMpICU+JQogICAgICAgIGRvKGNhbGN1bGF0ZV9vdXRjb21lKC4pKSAlPiUKICAgICAgICB1bmdyb3VwKCkgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdCgtIG1ldGhvZCkgJT4lCiAgICAgICAgYmluZF9jb2xzKG91dF9tZXRhX2RmW25vX2JhdGNoX2ZpbGVzLF1baSxdKSAKICAgIH0pICU+JQogICAgcHVycnI6OnJlZHVjZShiaW5kX3Jvd3MpCn0pCgpvdXRjb21lX2RmXzIKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQpwbF9kZiA8LSBvdXRjb21lX2RmXzIgJT4lIAogIG11dGF0ZShwcm9iX2JpbnM9IHNlcSgwLjMsIDEsIGJ5PTAuMDUpW2FzLm51bWVyaWMob3V0Y29tZV9kZl8yJHByb2JfYmlucyldKSAlPiUKICAgZmlsdGVyKGJhdGNoRWZmZWN0PT0wICYgc3RyX2RldGVjdChtZXRob2QsICJfYmF0Y2giLCBuZWdhdGUgPSBUUlVFKSkgJT4lIAogICBtdXRhdGUoVFBSPVRQLyhUUCtGTiksIEZQUj1GUC8oRlArVE4pKSAlPiUgCiAgIG11dGF0ZShUUFI9aWZlbHNlKGlzLm5hbihUUFIpLCAwLCBUUFIpLCAKICAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgICApICU+JSAKICAgIyBmaWx0ZXIocHJvYl9iaW5zID49IDAuNTUgJiBiYXRjaEVmZmVjdD09MCkgICU+JSAKICAgbXV0YXRlKGVucj1hcy5jaGFyYWN0ZXIoZW5yKSkgICU+JQogIGZpbHRlcihwb3AgJWluJSBjKCJFcnl0aHJvaWQyIiwgIkNhdWRhbF9uZXVyZWN0b2Rlcm0iKSkKCnBfdG9wIDwtIHBsX2RmICU+JQogIGZpbHRlcihiYXRjaEVmZmVjdD09IjAiKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihwcm9iX2JpbnMpLCBUUFIsIGNvbG9yPXBvcCwgc2hhcGU9cG9wKSkgKwogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41LCBwb3NpdGlvbj0ic3RhY2siLCBzaXplPTAuNSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IC4gJT4lIGdyb3VwX2J5KG1ldGhvZCwgcG9wLCBwcm9iX2JpbnMpICU+JSBzdW1tYXJpc2UoVFBSPW1lYW4oVFBSKSksIHNpemU9MiwKICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjUpKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTYpICsKICBmYWNldF9ncmlkKC5+bWV0aG9kLCBsYWJlbGxlcj1wbF9sYWJlbGxlcikgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT05MCkpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MiIpICsKICByZW1vdmVfeF9heGlzKCkKCnBfbWlkZGxlIDwtIHBsX2RmICU+JQogIGZpbHRlcihiYXRjaEVmZmVjdD09IjAiKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3Rvcihwcm9iX2JpbnMpLCBGUFIsIGNvbG9yPXBvcCwgc2hhcGU9cG9wKSkgKwogICMgZ2VvbV92aW9saW4oc2NhbGU9IndpZHRoIikgKwogICMgZ2VvbV9ib3hwbG90KG91dGxpZXIuYWxwaGEgPSAwKSArCiAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbShhbHBoYT0wLjUsIHBvc2l0aW9uPSJzdGFjayIsIHNpemU9MC41KSArCiAgZ2VvbV9wb2ludChkYXRhID0gLiAlPiUgZ3JvdXBfYnkobWV0aG9kLCBwb3AsIHByb2JfYmlucykgJT4lIHN1bW1hcmlzZShGUFI9bWVhbihGUFIsIG5hLnJtID0gVFJVRSkpLCBzaXplPTIsICAKICAgICAgICAgICAgIHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuNSkpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQyIikgKwogIGZhY2V0X2dyaWQoLn5tZXRob2QsIGxhYmVsbGVyPXBsX2xhYmVsbGVyKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuMSwgbGluZXR5cGU9MikgKwogIHhsYWIoIlAoQzEpIGJpbnMiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9OTAsIGhqdXN0PTEsIHZqdXN0PTAuNSkpIAoKcGxfQSA8LSBwX3RvcCAvIHBfbWlkZGxlICArCiAgcGxvdF9sYXlvdXQoZ3VpZGVzPSJjb2xsZWN0IikgJgogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIiwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSkpCgpwbF9BICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwiU2ZpZ19zaWduYWwybm9pc2VfcEMxLnBkZiIpLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDkpICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwiU2ZpZ19zaWduYWwybm9pc2VfcEMxLnBuZyIpLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDkpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQpwbF9zaWduYWwybm9pc2UgPC0gZnVuY3Rpb24obXlwb3AsIG15ZW5yLCBteXNlZWQsIG15bWV0aG9kKXsKICAgIGlmIChteW1ldGhvZD09ImRhc2VxIikgewogICAgcG9zX291dGNvbWUgPC0gIlBvc0xGQyIKICB9IGVsc2UgewogICAgcG9zX291dGNvbWUgPC0gIk5lZ0xGQyIKICB9CiAgcG9wVFBSIDwtIG91dGNvbWVfZGYgJT4lIGZpbHRlcihwb3A9PW15cG9wICYgZW5yPT1teWVuciAmIHNlZWQ9PW15c2VlZCAmIG1ldGhvZD09bXltZXRob2QpICU+JSBwdWxsKFRQUikKICByZXNfZmlsZSA8LSBsaXN0LmZpbGVzKG91dGRpciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm49IHBhc3RlMCgiLisiLCdlbWJyeW8nLCJfcG9wXyIsIG15cG9wLCAiX2VuciIsbXllbnIsIl9zZWVkIiwgbXlzZWVkLCAnLitiYXRjaEVmZmVjdDAnLCIuREFyZXN1bHRzLiIsbXltZXRob2QsIi5jc3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lcyA9IFRSVUUpCiAgCiAgcGwgPC0gcmVhZF9jc3YocmVzX2ZpbGUpICU+JQogICAgbXV0YXRlKG91dGNvbWUgPSBjYXNlX3doZW4ocHJlZD09Ik5vdERBIiAmIHRydWVfcHJvYiA8IDEtZW1icnlvX3RocmVzaCB+ICJGTiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZD09cG9zX291dGNvbWUgJiB0cnVlX3Byb2IgPCAxLWVtYnJ5b190aHJlc2ggfiAiVFAiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHByZWQ9PSJOb3REQSIgJiB0cnVlX3Byb2IgPiAxLWVtYnJ5b190aHJlc2ggfiAiVE4iCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSkgJT4lCiAgICBmaWx0ZXIob3V0Y29tZSAlaW4lIGMoJ1RQJywgIkZOIikpICU+JQogICAgZ2dwbG90KGFlcygxIC0gdHJ1ZV9wcm9iLCBjb2xvcj1vdXRjb21lKSkgKwogICAgZ2VvbV9kZW5zaXR5KHNpemU9MSkgKwogICAgeGxhYigiUChDMSkiKSArCiAgICBnZ3RpdGxlKHBhc3RlKCJUUFIgPSAiLCByb3VuZChwb3BUUFIsMikpKSArCiAgICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCkKICBwbAp9CgpwbF90b3AgPC0gd3JhcF9wbG90cyhsYXBwbHkoYygwLjc1LCAwLjg1LCAwLjk1KSwgZnVuY3Rpb24oeCkgcGxfc2lnbmFsMm5vaXNlKCJFcnl0aHJvaWQyIiwgeCwgbXlzZWVkID0gNDMsIG15bWV0aG9kID0gIm1pbG8iKSksIG5jb2w9MykKcGxfYm90IDwtIHdyYXBfcGxvdHMobGFwcGx5KGMoMC43NSwgMC44NSwgMC45NSksIGZ1bmN0aW9uKHgpIHBsX3NpZ25hbDJub2lzZSgiQ2F1ZGFsX25ldXJlY3RvZGVybSIsIHgsIG15c2VlZCA9IDQzLCBteW1ldGhvZCA9ICJtaWxvIikpLCBuY29sPTMpCnBsX0IgPC0gKHBsX3RvcCAvIHBsX2JvdCkgKwogIHBsb3RfbGF5b3V0KGd1aWRlcyA9ICJjb2xsZWN0IikgCgpwbF9CICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwiU2ZpZ19zaWduYWwybm9pc2UucGRmIiksIGhlaWdodCA9IDYsIHdpZHRoID0gOSkgKwogIGdnc2F2ZShwYXN0ZTAoZmlnZGlyLCJTZmlnX3NpZ25hbDJub2lzZS5wbmciKSwgaGVpZ2h0ID0gNiwgd2lkdGggPSA5KQoKYGBgCgojIyBCZW5jaG1hcmsgd2l0aCBiYXRjaCBlZmZlY3RzCgpSZWFkIG91dGNvbWUgZm9yIGVtYnJ5byAoYnVpbHQgd2l0aCB3cmFwcGVyIGBidWlsZF9vdXRjb21lLlJgKQoKYGBge3J9Cm91dGNvbWVfZGYgPC0gcmVhZF9jc3YoIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9vdXRjb21lX2VtYnJ5b192M19ub0JhdGNoLmNzdiIpCmBgYAoKUmVhZCBvdXRjb21lcyAobWFkZSB3aXRoIHdyYXBwZXIgYGJ1aWxkX291dGNvbWUuUmApCgpgYGB7cn0Kb3V0Y29tZV9kZl9iZSA8LSByZWFkX2NzdigiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL291dGNvbWVfZW1icnlvX3YzX3dCYXRjaC5jc3YiKSAlPiUKICBmaWx0ZXIocG9wIT0iTWl4ZWRfbWVzb2Rlcm0iKQpvdXRjb21lX2RmIDwtIGJpbmRfcm93cyhvdXRjb21lX2RmLCBvdXRjb21lX2RmX2JlKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9OH0KYmF0Y2hfbGFiZWxsZXIgPC0gYXNfbGFiZWxsZXIoYyhtaWxvPSJNaWxvXG4ofiBiYXRjaCArIGNvbmRpdGlvbikiLCBsb3V2YWluPSJMb3V2YWluXG4ofiBiYXRjaCArIGNvbmRpdGlvbikiLCBjeWRhcj0iQ3lkYXIiLCBkYXNlcT0nREFzZXEnKSkKCnBsX2RmIDwtIG91dGNvbWVfZGYgJT4lCiAgZmlsdGVyKG1ldGhvZCAhPSAibWlsbyIgJiBtZXRob2QgIT0gImxvdXZhaW4iICYgbWV0aG9kICE9ICJjeWRhcl9iYXRjaCIpICU+JQogIG11dGF0ZShGRFIgPSBGUC8oVFArRlApKSAlPiUKICBtdXRhdGUoVFBSPWlmZWxzZShpcy5uYW4oVFBSKSwgMCwgVFBSKSwKICAgICAgICAgRlBSPWlmZWxzZShpcy5uYW4oRlBSKSwgMCwgRlBSKSwKICAgICAgICAgIEZEUj1pZmVsc2UoaXMubmFuKEZEUiksIDAsIEZEUiksCiAgICAgICAgIFByZWNpc2lvbj1pZmVsc2UoaXMubmFuKFByZWNpc2lvbiksIDAsIFByZWNpc2lvbikpICU+JQogIG11dGF0ZShtZXRob2Q9c3RyX3JlbW92ZShtZXRob2QsIl9iYXRjaCIpKSAlPiUKICBmaWx0ZXIoZW5yID49IDAuOCkgJT4lCiAgbXV0YXRlKGVucj1hcy5jaGFyYWN0ZXIoZW5yKSkgCiAgCgpwX3RvcCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3RvcihiYXRjaEVmZmVjdCksIFRQUiwgY29sb3I9bWV0aG9kKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLmFscGhhID0gMCkgKwogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41LCBwb3NpdGlvbj0ic3RhY2siLCBzaXplPTAuNSkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0aG9kX2NvbG9ycywgbGFiZWxzPXNldE5hbWVzKG1ldGhvZF9sYWJlbHMsIG1ldGhvZF9uYW1lcykpICsKICBmYWNldF9ncmlkKC5+bWV0aG9kLCBsYWJlbGxlcj1iYXRjaF9sYWJlbGxlcikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkKICAKcF9ib3R0b20gPC0gcGxfZGYgJT4lCiAgZ2dwbG90KGFlcyhhcy5mYWN0b3IoYmF0Y2hFZmZlY3QpLCBGRFIsIGNvbG9yPW1ldGhvZCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5hbHBoYSA9IDApICsKICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKGFscGhhPTAuNSwgcG9zaXRpb249InN0YWNrIiwgc2l6ZT0wLjUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlPTIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBtZXRob2RfY29sb3JzLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgeGxhYigiQmF0Y2ggZWZmZWN0IG1hZ25pdHVkZSIpICsKICBmYWNldF9ncmlkKC5+bWV0aG9kLCBsYWJlbGxlcj1iYXRjaF9sYWJlbGxlcikKCihwX3RvcCAvIHBfYm90dG9tKSArIHBsb3RfbGF5b3V0KGd1aWRlcz0iY29sbGVjdCIpICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwgIm1haW5fYm1fYmF0Y2gucGRmIiksIHdpZHRoID0gMTEsIGhlaWdodCA9IDYpICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwgIm1haW5fYm1fYmF0Y2gucG5nIiksIHdpZHRoID0gMTEsIGhlaWdodCA9IDYpCmBgYAoKQnJlYWsgZG93biBieSBsb2dGQwpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTEwfQpwbF9kZiA8LSBvdXRjb21lX2RmICU+JQogIGZpbHRlcihtZXRob2QgIT0gIm1pbG8iICYgbWV0aG9kICE9ICJsb3V2YWluIiAmIG1ldGhvZCAhPSAiY3lkYXJfYmF0Y2giKSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgJT4lCiAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksCiAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLAogICAgICAgICBQcmVjaXNpb249aWZlbHNlKGlzLm5hbihQcmVjaXNpb24pLCAwLCBQcmVjaXNpb24pKSAlPiUKICBtdXRhdGUobWV0aG9kPXN0cl9yZW1vdmUobWV0aG9kLCJfYmF0Y2giKSkgJT4lCiAgbXV0YXRlKGVucj1hcy5jaGFyYWN0ZXIoZW5yKSkgCgpwX3RvcCA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3RvcihiYXRjaEVmZmVjdCksIFRQUiwgY29sb3I9bWV0aG9kKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLmFscGhhID0gMCkgKwogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41LCBwb3NpdGlvbj0ic3RhY2siLCBzaXplPTAuNSkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0aG9kX2NvbG9ycywgbGFiZWxzPXNldE5hbWVzKG1ldGhvZF9sYWJlbHMsIG1ldGhvZF9uYW1lcykpICsKICBmYWNldF9ncmlkKGVucn5tZXRob2QsIGxhYmVsbGVyPWxhYmVsbGVyKGVucj1lbnJfbGFiZWxsZXIyLCBtZXRob2Q9YmF0Y2hfbGFiZWxsZXIpKSArCiAgeGxhYigiQmF0Y2ggZWZmZWN0IG1hZ25pdHVkZSIpIAogIApwX2JvdHRvbSA8LSBwbF9kZiAlPiUKICBnZ3Bsb3QoYWVzKGFzLmZhY3RvcihiYXRjaEVmZmVjdCksIEZEUiwgY29sb3I9bWV0aG9kKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLmFscGhhID0gMCkgKwogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41LCBwb3NpdGlvbj0ic3RhY2siLCBzaXplPTAuNSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuMSwgbGluZXR5cGU9MikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE2KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1zZXROYW1lcyhtZXRob2RfbGFiZWxzLCBtZXRob2RfbmFtZXMpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbWV0aG9kX2NvbG9ycywgbGFiZWxzPXNldE5hbWVzKG1ldGhvZF9sYWJlbHMsIG1ldGhvZF9uYW1lcykpICsKICB4bGFiKCJCYXRjaCBlZmZlY3QgbWFnbml0dWRlIikgKwogIGZhY2V0X2dyaWQoZW5yfm1ldGhvZCwgbGFiZWxsZXI9bGFiZWxsZXIoZW5yPWVucl9sYWJlbGxlcjIsIG1ldGhvZD1iYXRjaF9sYWJlbGxlcikpCgoocF90b3AgfCBwX2JvdHRvbSkgKyBwbG90X2xheW91dChndWlkZXM9ImNvbGxlY3QiKSArIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gYygiQSIpKSArCiAgIyBnZ3NhdmUocGFzdGUwKGZpZ2RpciwgInN1cHBsX2JtX2JhdGNoX2xvZ0ZDLnBkZiIpLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSAxMCkgKwogICMgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJzdXBwbF9ibV9iYXRjaF9sb2dGQy5wbmciKSwgd2lkdGggPSAxNSwgaGVpZ2h0ID0gMTApCiAgZ2dzYXZlKHBhc3RlMCgifi9tb3VudC9nZHJpdmUvbWlsby9GaWd1cmVzL3Jlc3VibWlzc2lvbjIvc3VwcGxlbWVudGFyeS9zdXBwbF9maWdfYm1fYmF0Y2gucGRmIiksIHdpZHRoID0gMTgsIGhlaWdodCA9IDEwKQpgYGAKCgpXIGFuZCB3L28gYmF0Y2ggY29udHJvbAoKYGBge3J9CnBsX2RmIDwtIG91dGNvbWVfZGYgJT4lCiAgZmlsdGVyKG1ldGhvZCAlaW4lIGMoIm1pbG8iLCAibWlsb19iYXRjaCIpKSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgJT4lCiAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksCiAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLAogICAgICAgICBQcmVjaXNpb249aWZlbHNlKGlzLm5hbihQcmVjaXNpb24pLCAwLCBQcmVjaXNpb24pKSAlPiUKICBtdXRhdGUoZGVzaWduID0gaWZlbHNlKHN0cl9kZXRlY3QobWV0aG9kLCJfYmF0Y2giKSwgIn4gYmF0Y2ggKyBjb25kaXRpb24iLCAifiBjb25kaXRpb24iKSkgJT4lCiAgZmlsdGVyKGVuciA+PSAwLjgpICU+JQogIG11dGF0ZShlbnI9YXMuY2hhcmFjdGVyKGVucikpCgptZXRyaWM9J1RQUicKcGxfbGVmdCA8LXBsX2RmICU+JQogIG11dGF0ZShncm91cD1wYXN0ZShtZXRob2QsIGRlc2lnbikpICU+JQogIG11dGF0ZShtZXRob2Q9c3RyX3JlbW92ZShtZXRob2QsICJfYmF0Y2giKSkgJT4lCiAgZ2dwbG90KGFlcyhhcy5mYWN0b3IoYmF0Y2hFZmZlY3QpLCBUUFIsIGNvbG9yID1tZXRob2QpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuYWxwaGEgPSAwKSArCiAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbShhbHBoYT0wLjUsIHBvc2l0aW9uPSJzdGFjayIsIHNpemU9MC41KSAgKwogIGZhY2V0X2dyaWQoLn5kZXNpZ24pICsKICB0aGVtZV9idyhiYXNlX3NpemU9MTYpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjgsIGxpbmV0eXBlPTIpICsKICAjIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKGB+IGNvbmRpdGlvbmA9bWV0aG9kX2NvbG9yc1sibWlsbyJdLCAiYmxhY2siKSkgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1jKG1pbG89Ik1pbG8iLCBsb3V2YWluPSJMb3V2YWluIiwgY3lkYXI9IkN5ZGFyIiksIG5hbWU9IiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgptZXRyaWMgPSAiRkRSIgpwbF9yaWdodCA8LSAKICBwbF9kZiAlPiUKICBtdXRhdGUoZ3JvdXA9cGFzdGUobWV0aG9kLCBkZXNpZ24pKSAlPiUKICBtdXRhdGUobWV0aG9kPXN0cl9yZW1vdmUobWV0aG9kLCAiX2JhdGNoIikpICU+JQogIGdncGxvdChhZXMoYXMuZmFjdG9yKGJhdGNoRWZmZWN0KSwgRkRSLCBjb2xvciA9bWV0aG9kKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLmFscGhhID0gMCkgKwogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41LCBwb3NpdGlvbj0ic3RhY2siLCBzaXplPTAuNSkgICsKICBmYWNldF9ncmlkKC5+ZGVzaWduKSArCiAgeGxhYigiQmF0Y2ggZWZmZWN0IG1hZ25pdHVkZSIpICsKICB0aGVtZV9idyhiYXNlX3NpemU9MTYpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlPTIpICsKICAjIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKGB+IGNvbmRpdGlvbmA9bWV0aG9kX2NvbG9yc1sibWlsbyJdLCAiYmxhY2siKSkgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG1ldGhvZF9jb2xvcnMsIGxhYmVscz1jKG1pbG89Ik1pbG8iLCBsb3V2YWluPSJMb3V2YWluIiwgY3lkYXI9IkN5ZGFyIiksIG5hbWU9IiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSkpCgoKZGVzaWduX3Bsb3QgPC0gCiAgKHBsX2xlZnQgLyBwbF9yaWdodCkgKwogIHBsb3RfbGF5b3V0KGd1aWRlcz0iY29sbGVjdCIpICYKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEsMSkpIAoKZGVzaWduX3Bsb3QgKwogIGdnc2F2ZShwYXN0ZTAoZmlnZGlyLCAiYmF0Y2hFZmZlY3RfZGVzaWduLnBuZyIpLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDEwKSArCiAgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJiYXRjaEVmZmVjdF9kZXNpZ24ucGRmIiksIGhlaWdodCA9IDYsIHdpZHRoID0gMTAsIHVzZURpbmdiYXRzPUZBTFNFKQoKCmBgYAoKIyMgUGxvdCBleGFtcGxlcwoKVmlzdWFsaXplIG91dGNvbWUgaW4gVU1BUAoKYGBge3IsIGZpZy53aWR0aD0xNiwgZmlnLmhlaWdodD01fQpyZWFkX2lucHV0X2RhdGEgPC0gZnVuY3Rpb24oZW1icnlvX3NjZSwgaW5kaXIsIHBvcCwgZW5yLCBzZWVkLCBiYXRjaEVmZmVjdCwgcnVuX3VtYXA9VFJVRSl7CiAgcGNhX2ZpbGUgPC0gbGlzdC5maWxlcyhpbmRpciwgcGF0dGVybj1wYXN0ZTAocG9wLCIuKyIsICJlbnIiLGVuciwnX3NlZWQnLCBzZWVkLCAnLitiYXRjaEVmZmVjdCcsYmF0Y2hFZmZlY3QsIi5wY2EuY3N2IiksCiAgICAgICAgICAgICAgICAgICAgICAgICBmdWxsLm5hbWVzID0gVFJVRSkKICBjb2xkYXRhX2ZpbGUgPC0gbGlzdC5maWxlcyhpbmRpciwgcGF0dGVybj1wYXN0ZTAocG9wLCIuKyIsICJlbnIiLGVuciwnX3NlZWQnLCBzZWVkLCIuY29sZGF0YS5jc3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKQogIGNvbERhdGEoZW1icnlvX3NjZSkgPC0gcmVhZF9jc3YoY29sZGF0YV9maWxlKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkgJT4lIERhdGFGcmFtZSgpCiAgcmVkdWNlZERpbShlbWJyeW9fc2NlLCAicGNhX2JhdGNoIikgPC0gcmVhZF9jc3YocGNhX2ZpbGUpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoKSAlPiUgYXMubWF0cml4KCkKICBpZiAocnVuX3VtYXApIHsKICAgIGVtYnJ5b19zY2UgPC0gcnVuVU1BUChlbWJyeW9fc2NlLCBkaW1yZWQ9InBjYV9iYXRjaCIsIG5hbWUgPSAndW1hcF9iYXRjaCcsIG5fZGltcmVkPTE6MzApICAKICB9CiAgZW1icnlvX3NjZQp9CiMgCiMgcG9wPSJFcnl0aHJvaWQyIgojIGVucj0nMC43JwojIHNlZWQ9JzQzJwojIGJhdGNoRWZmZWN0PScwJwojIGluZGlyIDwtICJ+L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvIgojIAojIHNjZSA8LSByZWFkX2lucHV0X2RhdGEoZW1icnlvX3NjZSwgaW5kaXI9aW5kaXIsIHBvcD1wb3AsIGVucj1lbnIsIHNlZWQ9c2VlZCwgYmF0Y2hFZmZlY3Q9YmF0Y2hFZmZlY3QpCiMgCiMgcGxfbHMgPC0gbGFwcGx5KGMoIm1lbGQiLCAibWlsbyIsICJsb3V2YWluIiwgImRhc2VxIiksIGZ1bmN0aW9uKHgpIHBsb3Rfb3V0Y29tZV91bWFwKHNjZSwgeCwgcG9wLCBlbnIsIHNlZWQsIGJhdGNoRWZmZWN0LCB0cnVlPUZBTFNFKSkKIyBwbF90cnVlIDwtIHBsb3Rfb3V0Y29tZV91bWFwKHNjZSwgJ21pbG8nLCBwb3AsIGVuciwgc2VlZCwgYmF0Y2hFZmZlY3QsIHRydWU9VFJVRSkKIyBwbF90cnVlICsgCiMgICB3cmFwX3Bsb3RzKHBsX2xzLCBucm93ID0gMSwgZ3VpZGVzID0gImNvbGxlY3QiKSArCiMgICBwbG90X2xheW91dCh3aWR0aHMgPSBjKDEsNCkpCmBgYAoKUGxvdCBiZW5jaG1hcmsgZGVzaWduCgpgYGB7cn0KaW5kaXIgPC0gIn4vZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8iCnNjZSA8LSByZWFkX2lucHV0X2RhdGEoZW1icnlvX3NjZSA9IGVtYnJ5b19zY2UsIGluZGlyPWluZGlyLCBwb3A9Ik1lc2VuY2h5bWUiLCBlbnI9MC45LCBzZWVkPTQ0LCBiYXRjaEVmZmVjdD0wLCBydW5fdW1hcCA9IEZBTFNFKQp1bWFwX2JhdGhfZGYgPC0gZGF0YS5mcmFtZShyZWR1Y2VkRGltKHNjZSwgIlVNQVAiKSkgCmxpYnJhcnkoZ2dyYXN0cikKCiMjIEp1c3QgZW1iZWRkaW5nCnAxIDwtIHVtYXBfYmF0aF9kZiAlPiUKICAgIGRwbHlyOjpyZW5hbWUoVU1BUDE9WDEsIFVNQVAyPVgyKSAlPiUKICAgIGdncGxvdChhZXMoVU1BUDEsIFVNQVAyKSkgKyAKICAgIGdlb21fcG9pbnRfcmFzdChzaXplPTAuMSwgcmFzdGVyLmRwaSA9IDUwMCkgKwogICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemU9MTYpICsKICAgICAgZ3VpZGVzKGNvbG9yPWd1aWRlX2NvbG9yYmFyKHRpdGxlLnBvc2l0aW9uPSJ0b3AiLCB0aXRsZS5oanVzdCA9IDAuNSkpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICAgIHJhc3Rlcml6ZShnZW9tX3BvaW50KHNpemU9MC4xLCAgY29sb3I9ImdyZXkiKSwgZHBpID0gMzAwKQoKIyMgQzEgcHJvYmFiaWxpdHkKcDIgPC0gdW1hcF9iYXRoX2RmICU+JQogICAgZHBseXI6OnJlbmFtZShVTUFQMT1YMSwgVU1BUDI9WDIpICU+JQogICAgbXV0YXRlKHRydWU9c2NlJENvbmRpdGlvbjFfcHJvYikgJT4lCiAgICBtdXRhdGUodHJ1ZT1pZmVsc2UodHJ1ZSA8IDAuNSwgMC41LCB0cnVlKSkgJT4lCiAgICBhcnJhbmdlKHRydWUpICU+JQogICAgZ2dwbG90KGFlcyhVTUFQMSwgVU1BUDIsIGNvbG9yPXRydWUpKSArIAogICAgZ2VvbV9wb2ludF9yYXN0KHNpemU9MC4xLCByYXN0ZXIuZHBpID0gNTAwKSArCiAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhuYW1lPSJDMSBwcm9iYWJpbGl0eSIpICsKICAgIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE0KSArCiAgICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9jb2xvcmJhcih0aXRsZS5wb3NpdGlvbj0ibGVmdCIsIHRpdGxlLmhqdXN0ID0gMSwgdGl0bGUudmp1c3QgPSAxLCBiYXJ3aWR0aCA9IDAuNSwgYmFyaGVpZ2h0ID0gMykpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNzUsMC44NSksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgICAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgCiAgcmFzdGVyaXplKGdlb21fcG9pbnQoc2l6ZT0wLjEpLCBkcGkgPSAzMDApCgojIyBDb25kaXRpb24gbGFiZWxzCnAzIDwtIHVtYXBfYmF0aF9kZiAlPiUKICAgIGRwbHlyOjpyZW5hbWUoVU1BUDE9WDEsIFVNQVAyPVgyKSAlPiUKICAgIG11dGF0ZSh0cnVlX2xhYmVscz1zY2Ukc3ludGhfbGFiZWxzKSAlPiUKICAgIGdncGxvdChhZXMoVU1BUDEsIFVNQVAyLCBjb2xvcj10cnVlX2xhYmVscykpICsgCiAgICBnZW9tX3BvaW50X3Jhc3Qoc2l6ZT0wLjEsIHJhc3Rlci5kcGkgPSA1MDApICsKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIiwgbGFiZWxzPWMoQ29uZGl0aW9uMT0nQzEnLCBDb25kaXRpb24yPSJDMiIpLCBuYW1lPSIiKSArCiAgICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xNikgKwogICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTIpKSkgKwogICAgIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44NSwwLjk1KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICAgICB4bGFiKCJVTUFQMSIpICsgeWxhYigiVU1BUDIiKSAKCihwMSArIHAyICsgcDMpIAoKIyMgUXVhbnRpbGUgdGhyZXNob2xkCnFfdGhyZXNoIDwtIHF1YW50aWxlKHNjZSRDb25kaXRpb24xX3Byb2IpWzRdCmRhdGEuZnJhbWUocEMxID0gc2NlJENvbmRpdGlvbjFfcHJvYikgJT4lCiAgbXV0YXRlKHRydWVfbGFiZWxzPWlmZWxzZShzY2UkQ29uZGl0aW9uMV9wcm9iID4gcV90aHJlc2gsICdOZWdMRkMnLCAnTm90REEnKSApICU+JQogIGdncGxvdChhZXMocEMxLCBmaWxsPXRydWVfbGFiZWxzKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTEwMCkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZT0yNCkgKwogIHhsYWIoIlAoQzEpIikgKyB5bGFiKCIjIGNlbGxzIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHFfdGhyZXNoLCBjb2xvcj0iYmxhY2siLCBsaW5ldHlwZT0yLCBzaXplPTEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKE5lZ0xGQz0icmVkIiwgTm90REE9ImdyZXkiKSwgbGFiZWxzPWMoTmVnTEZDPSdjZWxsIGluIERBIHJlZ2lvbicsIE5vdERBPSJOb3QgREEiKSwgbmFtZT0iIikgKwogIHRoZW1lKGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkgKwogIGdnc2F2ZSgifi9tb3VudC9nZHJpdmUvbWlsby9GaWd1cmVzL2JlbmNobWFya192Mi9ibV9kZXNpZ25fcVRocmVzaC5wZGYiLCB3aWR0aD03LCBoZWlnaHQgPSA0KQoKcDQgPC0gdW1hcF9iYXRoX2RmICU+JQogICAgZHBseXI6OnJlbmFtZShVTUFQMT1YMSwgVU1BUDI9WDIpICU+JQogICAgbXV0YXRlKHRydWVfbGFiZWxzPWlmZWxzZShzY2UkQ29uZGl0aW9uMV9wcm9iID4gMC42LCAnTmVnTEZDJywgJ05vdERBJykgKSAlPiUKICAgIGdncGxvdChhZXMoVU1BUDEsIFVNQVAyLCBjb2xvcj10cnVlX2xhYmVscykpICsgCiAgICBnZW9tX3BvaW50X3Jhc3Qoc2l6ZT0wLjEsIHJhc3Rlci5kcGkgPSA1MDApICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKE5lZ0xGQz0icmVkIiwgTm90REE9ImdyZXkiKSwgbGFiZWxzPWMoTmVnTEZDPSdjZWxsIGluIERBIHJlZ2lvbicsIE5vdERBPSJOb3QgREEiKSwgbmFtZT0iIikgKwogICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemU9MTYpICsKICAgICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0yKSkpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuODUsMC45NSksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgICAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgCiAgICAjIGdnc2F2ZSgifi9tb3VudC9nZHJpdmUvbWlsby9GaWd1cmVzL2JlbmNobWFya192Mi9ibV9kZXNpZ25fcVRocmVzaF91bWFwLnBkZiIsIHdpZHRoPTcsIGhlaWdodCA9IDQpCgojIyBQcmVkaWN0aW9uCm91dGRpciA8LSAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2VtYnJ5by8iCnBvcD0iTWVzZW5jaHltZSIKZW5yPTAuOQpzZWVkPTQ0IApiYXRjaEVmZmVjdD0wCm1ldGhvZCA9ICJtaWxvIgpkYXRhX2lkID0gImVtYnJ5byIKcmVkX2RpbSA9ICJVTUFQIgoKcmVzX2ZpbGUgPC0gbGlzdC5maWxlcyhvdXRkaXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybj0gcGFzdGUwKCIuKyIsZGF0YV9pZCwiX3BvcF8iLCBwb3AsIl9lbnIiLGVuciwiX3NlZWQiLCBzZWVkLCAnLitiYXRjaEVmZmVjdCcsYmF0Y2hFZmZlY3QsIi5EQXJlc3VsdHMuIixtZXRob2QsIi5jc3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKQogIApzY2UkcHJlZGljdGVkIDwtIHJlYWRfY3N2KHJlc19maWxlKVtbInByZWQiXV0KCnBsIDwtIGRhdGEuZnJhbWUocmVkdWNlZERpbShzY2UsIHJlZF9kaW0pKSAlPiUKICAgIGRwbHlyOjpyZW5hbWVfYWxsKCB+IGMoIlVNQVAxIiwgIlVNQVAyIikgKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobWV0aG9kPW1ldGhvZCkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKHByZWRpY3RlZD1mYWN0b3Ioc2NlJHByZWRpY3RlZCwgbGV2ZWxzPWMoIk5lZ0xGQyIsICJQb3NMRkMiLCAnTm90REEnKSkpICU+JQogICAgZHBseXI6OmFycmFuZ2UoLSBwcmVkaWN0ZWQpICU+JQogICAgZ2dwbG90KGFlcyhVTUFQMSwgVU1BUDIsIGNvbG9yPXByZWRpY3RlZCkpICsgCiAgICBnZW9tX3BvaW50X3Jhc3Qoc2l6ZT0wLjEsIHJhc3Rlci5kcGkgPSA1MDApICsKICAgIGdlb21fcG9pbnRfcmFzdChkYXRhPSAuICU+JSBmaWx0ZXIocHJlZGljdGVkIT0iTm90REEiKSwgc2l6ZT0wLjIsIHJhc3Rlci5kcGkgPSA1MDApICsKICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoTmVnTEZDPSJyZWQiLCBOb3REQT0iZ3JleSIsIFBvc0xGQz0iYmx1ZSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoTmVnTEZDPSJFbnJpY2hlZCBpbiBDMSIsIE5vdERBPSJObyBEQSIsIFBvc0xGQz0iRGVwbGV0ZWQgaW4gQzEiKSwgbmFtZT0nJykgKwogICAgIGd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9MSkpKSArCiAgICAgdGhlbWVfY2xhc3NpYyhiYXNlX3NpemU9MTgpICsKICAgICB0aGVtZShsZWdlbmQucG9zaXRpb249YyguMTUsLjIpLCBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICAgICAgZmFjZXRfd3JhcChtZXRob2R+LikgICsKICByZW1vdmVfeF9heGlzKCkgKyByZW1vdmVfeV9heGlzKCkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpICsKICByYXN0ZXJpemUoZ2VvbV9wb2ludChzaXplPTAuMSksIGRwaSA9IDMwMCkgKwogIGdnc2F2ZSgifi9tb3VudC9nZHJpdmUvbWlsby9GaWd1cmVzL2JlbmNobWFya192Mi9ibV9kZXNpZ25fcHJlZF91bWFwLnBkZiIsIHdpZHRoPTQsIGhlaWdodCA9IDQpCgoKYGBgCgoKRGVzaWduIG1hdHJpeApgYGB7ciwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTN9CmRlc19wbCA8LSBkYXRhLmZyYW1lKGNvbERhdGEoc2NlKVssYygic3ludGhfbGFiZWxzIiwgInN5bnRoX3NhbXBsZXMiKV0pICU+JQogIGRpc3RpbmN0KHN5bnRoX2xhYmVscyxzeW50aF9zYW1wbGVzKSAlPiUKICBtdXRhdGUoc3ludGhfbGFiZWxzPXN0cl9yZW1vdmUoc3ludGhfbGFiZWxzLCJvbmRpdGlvbiIpLAogICAgICAgICBjb3VudD0xKSAlPiUKICBwaXZvdF93aWRlcihpZF9jb2xzID0gc3ludGhfc2FtcGxlcywgbmFtZXNfZnJvbT1zeW50aF9sYWJlbHMsIHZhbHVlc19mcm9tPWNvdW50LHZhbHVlc19maWxsPTApICU+JQogIHBpdm90X2xvbmdlcihjb2xzPWMoQzEsIEMyKSwgbmFtZXNfdG89InN5bnRoX2xhYmVscyIpICU+JQogIGdncGxvdChhZXMoc3ludGhfbGFiZWxzLCBzeW50aF9zYW1wbGVzKSkgKwogIGdlb21fdGlsZShmaWxsPSJ3aGl0ZSIsIGNvbG9yPSJibGFjayIsIHNpemU9MC44KSArCiAgZ2VvbV90aWxlKGRhdGE9LiAlPiUgZmlsdGVyKHZhbHVlPjApLCBhZXMoZmlsbD1zeW50aF9sYWJlbHMpLCBjb2xvcj0iYmxhY2siLCBzaXplPTEpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xNikgICArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsKICBndWlkZXMoZmlsbD0nbm9uZScpICsKICB4bGFiKCJTeW50aGV0aWMgXG5jb25kaXRpb24iKSArIHlsYWIoJ1N5bnRoZXRpYyBzYW1wbGVzJykgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCkpCgoocDEgKyBwMiArIHAzKSArIGRlc19wbCArIHA0ICsKICBwbG90X2xheW91dCh3aWR0aHM9YygxLDEsMSwwLjIsIDEpLCBuY29sPTUpICsKICBnZ3NhdmUoIn4vbW91bnQvZ2RyaXZlL21pbG8vRmlndXJlcy9iZW5jaG1hcmtfdjIvYm1fZXhhbXBsZS5wZGYiLCBoZWlnaHQgPSA0LCB3aWR0aCA9IDE0KSArCiAgZ2dzYXZlKCJ+L21vdW50L2dkcml2ZS9taWxvL0ZpZ3VyZXMvYmVuY2htYXJrX3YyL2JtX2V4YW1wbGUucG5nIiwgaGVpZ2h0ID0gNCwgd2lkdGggPSAxNCkKCmBgYAoKUGxvdCBiYXRjaCBlZmZlY3QKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xNX0KbGlicmFyeShnZ3Jhc3RyKQpiZV9zY2VfbHMgPC0gbGFwcGx5KGMoJzAnLCIwLjI1IiwgIjAuNSIsICIwLjc1IiwgIjEiKSwgZnVuY3Rpb24oeCkgcmVhZF9pbnB1dF9kYXRhKGVtYnJ5b19zY2UsIGluZGlyLCBwb3AsIGVuciwgc2VlZCwgeCkpCgptZXRob2Q9Im1pbG8iCgpwb3AKIyMgUGxvdCBjb25kaXRpb24gcHJvYmFiaWxpdHkgCmJlX3BsX2xzIDwtIGxhcHBseShiZV9zY2VfbHMsIGZ1bmN0aW9uKHNjZSkgewogIGNvbGRhdGFfZmlsZSA8LSBsaXN0LmZpbGVzKGluZGlyLCBwYXR0ZXJuPXBhc3RlMChwb3AsIi4rIiwgImVuciIsZW5yLCIuKyIsJ3NlZWQnLCBzZWVkLCAiLmNvbGRhdGEuY3N2IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKQogIGNvbERhdGEoc2NlKSA8LSBEYXRhRnJhbWUocmVhZF9jc3YoY29sZGF0YV9maWxlKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkpCiAgZGF0YS5mcmFtZShyZWR1Y2VkRGltKHNjZSwgInVtYXBfYmF0Y2giKSkgJT4lCnJlbmFtZShVTUFQMT1YMSwgVU1BUDI9WDIpICU+JQogICAgbXV0YXRlKHRydWU9c2NlJENvbmRpdGlvbjFfcHJvYikgJT4lCiAgICBtdXRhdGUodHJ1ZT1pZmVsc2UodHJ1ZSA8IDAuNSwgMC41LCB0cnVlKSkgJT4lCiAgICBhcnJhbmdlKHRydWUpICU+JQogICAgZ2dwbG90KGFlcyhVTUFQMSwgVU1BUDIsIGNvbG9yPXRydWUpKSArIAogICAgZ2VvbV9wb2ludF9yYXN0KHNpemU9MC4xLCByYXN0ZXIuZHBpID0gNTAwKSArCiAgICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhuYW1lPSJDMSBwcm9iYWJpbGl0eSIpICsKICAgIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE0KSArCiAgICAgIGd1aWRlcyhjb2xvcj1ndWlkZV9jb2xvcmJhcih0aXRsZS5wb3NpdGlvbj0ibGVmdCIsIHRpdGxlLmhqdXN0ID0gMSwgdGl0bGUudmp1c3QgPSAxLCBiYXJ3aWR0aCA9IDAuNSwgYmFyaGVpZ2h0ID0gMykpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNzUsMC44NSksIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgICAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgCiAgfQopCgoKIyMgUGxvdCBiYXRjaApiZV9wbF9sczIgPC0gbGFwcGx5KGJlX3NjZV9scywgZnVuY3Rpb24oc2NlKSB7CiAgY29sZGF0YV9maWxlIDwtIGxpc3QuZmlsZXMoaW5kaXIsIHBhdHRlcm49cGFzdGUwKHBvcCwiLisiLCAiZW5yIixlbnIsIi4rIiwnc2VlZCcsIHNlZWQsICIuY29sZGF0YS5jc3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lcyA9IFRSVUUpCiAgY29sRGF0YShzY2UpIDwtIERhdGFGcmFtZShyZWFkX2Nzdihjb2xkYXRhX2ZpbGUpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoKSkKICBkYXRhLmZyYW1lKHJlZHVjZWREaW0oc2NlLCAidW1hcF9iYXRjaCIpKSAlPiUKICAgIHJlbmFtZShVTUFQMT1YMSwgVU1BUDI9WDIpICU+JQogICAgbXV0YXRlKHRydWU9c2NlJHN5bnRoX2JhdGNoZXMpICU+JQogICAgZ2dwbG90KGFlcyhVTUFQMSwgVU1BUDIsIGNvbG9yPXRydWUpKSArCiAgICBnZW9tX3BvaW50X3Jhc3Qoc2l6ZT0wLjEsIHJhc3Rlci5kcGkgPSA1MDApICsKICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChuYW1lPSJCYXRjaCIsIG9wdGlvbj0iY2l2aWRpcyIpICsKICAgICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xOCkgKwogICAgICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0yKSkpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpIAogIH0KKQoKcHRvcCA8LSB3cmFwX3Bsb3RzKGJlX3BsX2xzLCBuY29sPTEsIGd1aWRlcz0iY29sbGVjdCIpICYKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSAKcGJvdHRvbSA8LSB3cmFwX3Bsb3RzKGJlX3BsX2xzMiwgbmNvbD0xLCBndWlkZXM9ImNvbGxlY3QiKQoKKHB0b3AgfCBwYm90dG9tKSArCiAgcGxvdF9sYXlvdXQoZ3VpZGVzPSJjb2xsZWN0IikgKwogIGdnc2F2ZShwYXN0ZTAoZmlnZGlyLCAiYmF0Y2hFZmZlY3RfVU1BUHMucGRmIiksIGhlaWdodD0xMywgd2lkdGggPSA4KSArCiAgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJiYXRjaEVmZmVjdF9VTUFQcy5wbmciKSwgaGVpZ2h0PTEzLCB3aWR0aCA9IDgpCmBgYAoKRGVzaWduIG1hdHJpeCB3IGJhdGNoIGVmZmVjdAoKYGBge3IsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTN9Cm0xIDwtIGRhdGEuZnJhbWUoY29sRGF0YShzY2UpWyxjKCJzeW50aF9sYWJlbHMiLCAic3ludGhfc2FtcGxlcyIsICdzeW50aF9iYXRjaGVzJyldKSAlPiUKICBkaXN0aW5jdChzeW50aF9sYWJlbHMsc3ludGhfc2FtcGxlcykgJT4lCiAgbXV0YXRlKHN5bnRoX2xhYmVscz1zdHJfcmVtb3ZlKHN5bnRoX2xhYmVscywib25kaXRpb24iKSwKICAgICAgICAgY291bnQ9MSkgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHN5bnRoX3NhbXBsZXMsIG5hbWVzX2Zyb209c3ludGhfbGFiZWxzLCB2YWx1ZXNfZnJvbT1jb3VudCx2YWx1ZXNfZmlsbD0wKSAlPiUKICBwaXZvdF9sb25nZXIoY29scz1jKEMxLCBDMiksIG5hbWVzX3RvPSJzeW50aF9sYWJlbHMiKSAlPiUKICBnZ3Bsb3QoYWVzKHN5bnRoX2xhYmVscywgc3ludGhfc2FtcGxlcykpICsKICBnZW9tX3RpbGUoZmlsbD0id2hpdGUiLCBjb2xvcj0iYmxhY2siLCBzaXplPTEpICsKICBnZW9tX3RpbGUoZGF0YT0uICU+JSBmaWx0ZXIodmFsdWU+MCksIGFlcyhmaWxsPXN5bnRoX2xhYmVscyksIGNvbG9yPSJibGFjayIsIHNpemU9MSkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE2KSAgICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKwogIGd1aWRlcyhmaWxsPSdub25lJykgKwogIHhsYWIoIlN5bnRoZXRpYyBcbmNvbmRpdGlvbiIpICsgeWxhYignU3ludGhldGljIHNhbXBsZXMnKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSkKCm0yIDwtIGRhdGEuZnJhbWUoY29sRGF0YShzY2UpWyxjKCJzeW50aF9sYWJlbHMiLCAic3ludGhfc2FtcGxlcyIsICdzeW50aF9iYXRjaGVzJyldKSAlPiUKICBkaXN0aW5jdChzeW50aF9sYWJlbHMsc3ludGhfc2FtcGxlcywgc3ludGhfYmF0Y2hlcykgJT4lCiAgbXV0YXRlKHN5bnRoX2xhYmVscz1zdHJfcmVtb3ZlKHN5bnRoX2xhYmVscywib25kaXRpb24iKSwKICAgICAgICAgY291bnQ9MSkgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHN5bnRoX3NhbXBsZXMsIG5hbWVzX2Zyb209c3ludGhfYmF0Y2hlcywgdmFsdWVzX2Zyb209Y291bnQsdmFsdWVzX2ZpbGw9MCkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHM9YyhCMSwgQjIpLCBuYW1lc190bz0ic3ludGhfYmF0Y2hlcyIpICU+JQogIGdncGxvdChhZXMoc3ludGhfYmF0Y2hlcywgc3ludGhfc2FtcGxlcykpICsKICBnZW9tX3RpbGUoZmlsbD0id2hpdGUiLCBjb2xvcj0iYmxhY2siLCBzaXplPTEpICsKICBnZW9tX3RpbGUoZGF0YT0uICU+JSBmaWx0ZXIodmFsdWU+MCksIGFlcyhmaWxsPXN5bnRoX2JhdGNoZXMpLCBjb2xvcj0iYmxhY2siLCBzaXplPTEpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xNikgICArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uPSJjaXZpZGlzIikgKwogIGd1aWRlcyhmaWxsPSdub25lJykgKwogIHhsYWIoIlN5bnRoZXRpYyBcbmJhdGNoIikgKyB5bGFiKCdTeW50aGV0aWMgc2FtcGxlcycpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCkpCgoobTEgKyBtMikgKwojIChwMSArIHAyICsgcDMpICsgZGVzX3BsICsKICBwbG90X2xheW91dCh3aWR0aHM9YygxLDEpLCBuY29sPTIpICsKICBnZ3NhdmUocGFzdGUwKGZpZ2RpciwgImJtX2Rlc2lnbl9iYXRjaC5wZGYiKSwgaGVpZ2h0ID0gNCwgd2lkdGggPSA0KQpgYGAKCjwhLS0gYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTE0fSAtLT4KPCEtLSBvdXRjb21lX2RmICU+JSAtLT4KPCEtLSAgIG11dGF0ZShGRFIgPSBGUC8oVFArRlApKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoVFBSPWlmZWxzZShpcy5uYW4oVFBSKSwgMCwgVFBSKSwgLS0+CjwhLS0gICAgICAgICAgRlBSPWlmZWxzZShpcy5uYW4oRlBSKSwgMCwgRlBSKSwgLS0+CjwhLS0gICAgICAgICAgUHJlY2lzaW9uPWlmZWxzZShpcy5uYW4oUHJlY2lzaW9uKSwgMCwgUHJlY2lzaW9uKSkgJT4lIC0tPgo8IS0tICAgZ3JvdXBfYnkobWV0aG9kLCBEQV90aHJlc2gsIGJhdGNoRWZmZWN0KSAlPiUgLS0+CjwhLS0gICBzdW1tYXJpc2UobWVhbl9GRFI9bWVhbihGRFIpLCAgLS0+CjwhLS0gICAgICAgICAgICAgc2RfRkRSPXNkKEZEUikvc3FydChuKCkpLCAtLT4KPCEtLSAgICAgICAgICAgICBtZWFuX1RQUj1tZWFuKFRQUiksICAtLT4KPCEtLSAgICAgICAgICAgICBzZF9UUFI9c2QoVFBSKS9zcXJ0KG4oKSkpICU+JSAtLT4KPCEtLSAgIGdncGxvdChhZXMoREFfdGhyZXNoLCBiYXRjaEVmZmVjdCkpICsgLS0+CjwhLS0gICBnZW9tX3RpbGUoYWVzKGZpbGw9bWVhbl9UUFIpKSArIC0tPgo8IS0tICAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArIC0tPgo8IS0tICAgZmFjZXRfd3JhcChtZXRob2R+LiwgbmNvbD0yKSArIC0tPgo8IS0tICAgdGhlbWVfYncoYmFzZV9zaXplPTE2KSArIC0tPgoKPCEtLSBvdXRjb21lX2RmICU+JSAtLT4KPCEtLSAgIG11dGF0ZShGRFIgPSBGUC8oVFArRlApKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoVFBSPWlmZWxzZShpcy5uYW4oVFBSKSwgMCwgVFBSKSwgLS0+CjwhLS0gICAgICAgICAgRlBSPWlmZWxzZShpcy5uYW4oRlBSKSwgMCwgRlBSKSwgLS0+CjwhLS0gICAgICAgICAgRkRSPWlmZWxzZShpcy5uYW4oRkRSKSwgMCwgRkRSKSwgLS0+CjwhLS0gICAgICAgICAgUHJlY2lzaW9uPWlmZWxzZShpcy5uYW4oUHJlY2lzaW9uKSwgMCwgUHJlY2lzaW9uKSkgJT4lIC0tPgo8IS0tICAgZ3JvdXBfYnkobWV0aG9kLCBEQV90aHJlc2gsIGJhdGNoRWZmZWN0KSAlPiUgLS0+CjwhLS0gICBzdW1tYXJpc2UobWVhbl9GRFI9bWVhbihGRFIpLCAgLS0+CjwhLS0gICAgICAgICAgICAgc2RfRkRSPXNkKEZEUikvc3FydChuKCkpLCAtLT4KPCEtLSAgICAgICAgICAgICBtZWFuX1RQUj1tZWFuKFRQUiksICAtLT4KPCEtLSAgICAgICAgICAgICBzZF9UUFI9c2QoVFBSKS9zcXJ0KG4oKSkpICU+JSAtLT4KPCEtLSAgIGdncGxvdChhZXMoREFfdGhyZXNoLCBiYXRjaEVmZmVjdCkpICsgLS0+CjwhLS0gICBnZW9tX3RpbGUoYWVzKGZpbGw9bWVhbl9GRFIpKSArIC0tPgo8IS0tICAgc2NhbGVfZmlsbF92aXJpZGlzX2MoZGlyZWN0aW9uID0gLTEpICsgLS0+CjwhLS0gICBmYWNldF93cmFwKG1ldGhvZH4uLCBuY29sPTIpICsgLS0+CjwhLS0gICB0aGVtZV9idyhiYXNlX3NpemU9MTYpIC0tPgo8IS0tIGBgYCAtLT4KCgoKIyMgQ29ycmVjdGluZyBiYXRjaCBlZmZlY3QKCkxvYWQgc2ltdWxhdGlvbnMgd2l0aCBiYXRjaCBlZmZlY3RzIGFuZCBjb3JyZWN0IHdpdGggTU5OCgpgYGB7cn0KbGlicmFyeShiYXRjaGVsb3IpCgptbm5fY29ycmVjdF9iYXRjaF9lZmZlY3QgPC0gZnVuY3Rpb24oYmVfc2NlLCBrPTUwKXsKICAjIyBTcGxpdCBpbiB0d28gU0NFIG9iamVjdHMKICBiMV9iZV9zY2UgPC0gYmVfc2NlWyxiZV9zY2Ukc3ludGhfYmF0Y2hlcz09IkIxIl0KICBiMl9iZV9zY2UgPC0gYmVfc2NlWyxiZV9zY2Ukc3ludGhfYmF0Y2hlcz09IkIyIl0KICAKICBiZV9tbm4gPC0gcmVkdWNlZE1OTihyZWR1Y2VkRGltKGIxX2JlX3NjZSwgInBjYS5jb3JyZWN0ZWQiKSwgcmVkdWNlZERpbShiMl9iZV9zY2UsICJwY2EuY29ycmVjdGVkIiksIGs9aykKICByZWR1Y2VkRGltKGJlX3NjZSwgInBjYS5NTk4iKSA8LSBiZV9tbm4kY29ycmVjdGVkW2NvbG5hbWVzKGJlX3NjZSksXQogIGJlX3NjZQogIH0KCiMjIFNpbXVsYXRlIGJhdGNoIGVmZmVjdHMgb2YgZGlmZmVyZW50IG1hZ25pdHVkZQpzYXZlX2NvcnJlY3RlZF9iZSA8LSBmdW5jdGlvbihwb3AsIHBvcF9lbnIsIHNlZWQsIGJlX3NkKXsKICAjIyBMb2FkIGNvbGRhdGEgYW5kIFBDQQogIG91dGRpciA8LSAnL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL3N5bnRoZXRpY19kYXRhLycKICBvdXRwcmVmaXggPC0gc3RyX2MoImJlbmNobWFya19lbWJyeW9fcG9wXyIsIHBvcCwgJ19lbnInLCBwb3BfZW5yLCAiX3NlZWQiLCBzZWVkKQogIGNvbGRhdGEgPC0gcmVhZF9jc3YocGFzdGUwKG91dGRpciwgb3V0cHJlZml4LCAiLmNvbGRhdGEuY3N2IikpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoKQogIFhfcGNhIDwtcmVhZF9jc3Yoc3RyX2Mob3V0ZGlyLCBvdXRwcmVmaXgsICJfYmF0Y2hFZmZlY3QiLCBiZV9zZCwgIi5wY2EuY3N2IikpICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoKQogIAogICMjIEFkZCByZWR1Y2VkIGRpbSArIGNvbGRhdGEgdG8gc2NlCiAgY29sRGF0YShlbWJyeW9fc2NlKSA8LSBEYXRhRnJhbWUoY29sZGF0YSkKICByZWR1Y2VkRGltKGVtYnJ5b19zY2UsICJwY2FfYmF0Y2giKSA8LSBhcy5tYXRyaXgoWF9wY2EpCiAgCiAgc2V0LnNlZWQoc2VlZCkKICBzY2VfYmUgPC0gbW5uX2NvcnJlY3RfYmF0Y2hfZWZmZWN0KGVtYnJ5b19zY2UpCiAgWF9wY2EgPC0gcmVkdWNlZERpbShzY2VfYmUsICJwY2EuTU5OIikKICAjIyBTYXZlIHJlZHVjZWQgZGltcwogIHdyaXRlX2Nzdihhcy5kYXRhLmZyYW1lKFhfcGNhKSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCksIHN0cl9jKG91dGRpciwgb3V0cHJlZml4LCAiX2JhdGNoRWZmZWN0IiwgYmVfc2QsIi5NTk5jb3JyZWN0ZWQucGNhLmNzdiIpKQogIH0KCmJlX3NkcyA8LSB1bmlxdWUob3V0X21ldGFfZGYkYmF0Y2hFZmZlY3QpCnBvcHMgPC0gdW5pcXVlKG91dF9tZXRhX2RmJHBvcCkKc2VlZHM9Yyg0MykKCmZvciAocG9wIGluIHBvcHMpIHsKICAgIGZvciAoc2VlZCBpbiBzZWVkcykgewogICAgICBmb3IgKGJlX3NkIGluIGMoMC41LCAwLjc1LCAxKSkgewogICAgICBwb3BfZW5yID0gMC44CiAgICAgIHNhdmVfY29ycmVjdGVkX2JlKHBvcCwgcG9wX2Vuciwgc2VlZCwgYmVfc2QpCiAgICAgIH0KICAgIH0KICB9CmBgYAoKUmVhZCBhbGwgcmVzdWx0cyAocnVubmVkIGluIHdyYXBwZXIgYHN1Ym1pdF9gKQoKYGBge3J9Cm91dGRpciA8LSAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL01OTl9jb3JyZWN0ZWQvIgpyZXNfZmlsZXMgPC0gbGlzdC5maWxlcyhvdXRkaXIsIHBhdHRlcm49Ii4rREFyZXN1bHRzLisuY3N2IikKcmVzX2ZpbGVzX2Z1bGwgPC0gbGlzdC5maWxlcyhvdXRkaXIsIHBhdHRlcm49Ii4rREFyZXN1bHRzLisuY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpCiMgaW5fZmlsZXMgPC0gbGlzdC5maWxlcygifi9kYXRhL21pbG9fYmVuY2htYXJrL3N5bnRoZXRpY19kYXRhLyIsIHBhdHRlcm49Il9lbnIwLls3OF0uK2NvbGRhdGEuY3N2IikKCiMjIE1ha2UgZGF0YSBmcmFtZSB3IGJlbmNobWFyayBwYXJhbWV0ZXJzCm1ubl9vdXRfbWV0YV9kZiA8LSBkYXRhLmZyYW1lKGZpbGVfaWQgPSBzdHJfcmVtb3ZlX2FsbChyZXNfZmlsZXMsICJiZW5jaG1hcmtfZW1icnlvX3BvcF98LmNzdiIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCAiYmF0Y2hFZmZlY3QiKSkgJT4lCiAgbXV0YXRlKHNlZWQ9c3RyX3JlbW92ZShzZWVkLCAic2VlZCIpLCBiYXRjaEVmZmVjdD1zdHJfcmVtb3ZlKGJhdGNoRWZmZWN0LCAiYmF0Y2hFZmZlY3QiKSkgCgojIyBMb2FkIHJlc3VsdHMKbW5uX291dGNvbWVfZGYgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbCksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2ldKSAlPiUKICAgICAgLm91dGNvbWVfYnlfcHJvYihkYV91cHBlciA9IGVtYnJ5b190aHJlc2gpICU+JQogICAgICBtdXRhdGUoREFfdGhyZXNoPWVtYnJ5b190aHJlc2gpICU+JQogICAgICB1bmdyb3VwKCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoLSBtZXRob2QpICU+JQogICAgICBiaW5kX2NvbHMobW5uX291dF9tZXRhX2RmW2ksXSkgCiAgcG9wX2VuciA8LSBhcy5udW1lcmljKG1ubl9vdXRfbWV0YV9kZltpLCJlbnIiXSkKICBiZW5jaG1hcmtfZGYKICB9KSAlPiUKICBwdXJycjo6cmVkdWNlKGJpbmRfcm93cykKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTF9Cm5vX2JlIDwtIG91dGNvbWVfZGYgJT4lCiAgZmlsdGVyKGJhdGNoRWZmZWN0PT0iMCIpICU+JQogIG11dGF0ZShGRFIgPSBGUC8oVFArRlApKSAKCnVuY29ycmVjdGVkX2JlIDwtIG91dGNvbWVfZGYgJT4lCiAgZmlsdGVyKGJhdGNoRWZmZWN0ICVpbiUgYygiMC41IiwgIjAuNzUiLCAnMScpKSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgCgpwbF9kZiA8LSBtbm5fb3V0Y29tZV9kZiAlPiUKICBmaWx0ZXIoZW5yID4gMC42KSAlPiUKICAgbXV0YXRlKGJhdGNoRWZmZWN0ID0gc3RyX3JlbW92ZShiYXRjaEVmZmVjdCwgIi5NTk5jb3JyZWN0ZWQiKSkgJT4lCiAgbXV0YXRlKEZEUiA9IEZQLyhUUCtGUCkpICU+JQogIG11dGF0ZShUUFI9aWZlbHNlKGlzLm5hbihUUFIpLCAwLCBUUFIpLAogICAgICAgICBGUFI9aWZlbHNlKGlzLm5hbihGUFIpLCAwLCBGUFIpLAogICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLAogICAgICAgICBQcmVjaXNpb249aWZlbHNlKGlzLm5hbihQcmVjaXNpb24pLCAwLCBQcmVjaXNpb24pKSAlPiUKICBtdXRhdGUocG9wPXN0cl9yZXBsYWNlKHBvcCwgIl8iLCAiICIpKSAlPiUKICAjIG11dGF0ZShwb3Bfc2l6ZT1wb3Bfc2l6ZXNbcG9wXSkgICU+JQogICMgYXJyYW5nZShwb3Bfc2l6ZSkgJT4lCiAgbXV0YXRlKHBvcD1mYWN0b3IocG9wLCBsZXZlbHM9dW5pcXVlKHBvcCkpKSAlPiUKICBtdXRhdGUoc2VlZD1hcy5udW1lcmljKHNlZWQpLCBlbnI9YXMubnVtZXJpYyhlbnIpLCBiYXRjaEVmZmVjdD1hcy5udW1lcmljKGJhdGNoRWZmZWN0KSkKCnBsX3RvcCA8LSBiaW5kX3Jvd3MobXV0YXRlKG5vX2JlLCBjbGFzcz0ibm8gQmF0Y2ggRWZmZWN0IiksCiAgbXV0YXRlKHVuY29ycmVjdGVkX2JlLCBjbGFzcz0iVW5jb3JyZWN0ZWQiKSwKICBtdXRhdGUocGxfZGYsIGNsYXNzPSJNTk4gY29ycmVjdGVkIikpICU+JQogIG11dGF0ZShjbGFzcz1mYWN0b3IoY2xhc3MsIGxldmVscz1jKCJubyBCYXRjaCBFZmZlY3QiLCAiTU5OIGNvcnJlY3RlZCIsICJVbmNvcnJlY3RlZCIpKSkgJT4lCiAgICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgJT4lCiAgbXV0YXRlKFRQUj1pZmVsc2UoaXMubmFuKFRQUiksIDAsIFRQUiksCiAgICAgICAgIEZQUj1pZmVsc2UoaXMubmFuKEZQUiksIDAsIEZQUiksCiAgICAgICAgIEZEUj1pZmVsc2UoaXMubmFuKEZEUiksIDAsIEZEUiksCiAgICAgICAgIFByZWNpc2lvbj1pZmVsc2UoaXMubmFuKFByZWNpc2lvbiksIDAsIFByZWNpc2lvbikpICU+JQogIGZpbHRlcihtZXRob2QgIT0gIm1pbG9fYmF0Y2giICYgbWV0aG9kICE9ImxvdXZhaW5fYmF0Y2giICYgbWV0aG9kICE9ImN5ZGFyX2JhdGNoIikgJT4lCiAgZ2dwbG90KGFlcyhhcy5mYWN0b3IoYmF0Y2hFZmZlY3QpLCBjb2xvcj1tZXRob2QsIFRQUikpICsgCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2l6ZSA9IDAuNSkgKwogIGZhY2V0X2dyaWQoLn5jbGFzcywgc3BhY2U9ImZyZWUiLCBzY2FsZXM9ImZyZWUiKSArCiAgc2NhbGVfY29sb3JfbWV0aG9kcygpICsKICBzY2FsZV9maWxsX21ldGhvZHMoKSArCiAgdGhlbWVfYncoYmFzZV9zaXplPTE2KSArCiAgeGxhYigiQmF0Y2ggZWZmZWN0IG1hZ25pdHVkZSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpCgpwbF9ib3R0b20gPC0gYmluZF9yb3dzKG11dGF0ZShub19iZSwgY2xhc3M9Im5vIEJhdGNoIEVmZmVjdCIpLAogIG11dGF0ZSh1bmNvcnJlY3RlZF9iZSwgY2xhc3M9IlVuY29ycmVjdGVkIiksCiAgbXV0YXRlKHBsX2RmLCBjbGFzcz0iTU5OIGNvcnJlY3RlZCIpKSAlPiUKICBtdXRhdGUoY2xhc3M9ZmFjdG9yKGNsYXNzLCBsZXZlbHM9Yygibm8gQmF0Y2ggRWZmZWN0IiwgIk1OTiBjb3JyZWN0ZWQiLCAiVW5jb3JyZWN0ZWQiKSkpICU+JQogICAgbXV0YXRlKEZEUiA9IEZQLyhUUCtGUCkpICU+JQogIG11dGF0ZShUUFI9aWZlbHNlKGlzLm5hbihUUFIpLCAwLCBUUFIpLAogICAgICAgICBGUFI9aWZlbHNlKGlzLm5hbihGUFIpLCAwLCBGUFIpLAogICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLAogICAgICAgICBQcmVjaXNpb249aWZlbHNlKGlzLm5hbihQcmVjaXNpb24pLCAwLCBQcmVjaXNpb24pKSAlPiUKICBmaWx0ZXIobWV0aG9kICE9ICJtaWxvX2JhdGNoIiAmIG1ldGhvZCAhPSJsb3V2YWluX2JhdGNoIiAmIG1ldGhvZCAhPSJjeWRhcl9iYXRjaCIpICU+JQogIGdncGxvdChhZXMoYXMuZmFjdG9yKGJhdGNoRWZmZWN0KSwgY29sb3I9bWV0aG9kLCBGRFIpKSArIAogIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAwLjUpICsKICBmYWNldF9ncmlkKC5+Y2xhc3MsIHNwYWNlPSJmcmVlIiwgc2NhbGVzPSJmcmVlIikgKwogIHNjYWxlX2NvbG9yX21ldGhvZHMoKSArCiAgc2NhbGVfZmlsbF9tZXRob2RzKCkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZT0xNikgKwogIHhsYWIoIkJhdGNoIGVmZmVjdCBtYWduaXR1ZGUiKQoKbW5uX3Bsb3QgPC0gKHBsX3RvcCAvIHBsX2JvdHRvbSArCiAgcGxvdF9sYXlvdXQoZ3VpZGVzPSJjb2xsZWN0IikgJgogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikpICsKICBnZ3NhdmUocGFzdGUwKCJ+L21vdW50L2dkcml2ZS9taWxvL0ZpZ3VyZXMvcmVzdWJtaXNzaW9uMi9zdXBwbGVtZW50YXJ5L3N1cHBsX2ZpZ19ibV9NTk4ucGRmIiksIGhlaWdodCA9IDYsIHdpZHRoID0gOCkgCiAgCm1ubl9wbG90CmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQoobW5uX3Bsb3QgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikpICsgCiAgIyBnZ3NhdmUocGFzdGUwKGZpZ2RpciwgImJhdGNoRWZmZWN0X01OTmNvcnJlY3RlZC5wbmciKSwgaGVpZ2h0ID0gNiwgd2lkdGggPSAxMCkgKwogICMgZ2dzYXZlKHBhc3RlMChmaWdkaXIsICJiYXRjaEVmZmVjdF9NTk5jb3JyZWN0ZWQucGRmIiksIGhlaWdodCA9IDYsIHdpZHRoID0gMTApIApnZ3NhdmUoIn4vbW91bnQvZ2RyaXZlL21pbG8vRmlndXJlcy9yZXN1Ym1pc3Npb24vc3VwcGxlbWVudGFyeS9zdXBwbF9maWdfYm1fTU5OLnBkZiIsIGhlaWdodCA9IDYsIHdpZHRoID0gMTApCmBgYAoKClBsb3QgVU1BUApgYGB7ciwgZmlnLndpZHRoPTYsZmlnLmhlaWdodD03fQpYX3BjYV9tbm4gPC0gcmVhZF9jc3YoIi9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS9iZW5jaG1hcmtfZW1icnlvX3BvcF9Tb21pdGljX21lc29kZXJtX2VucjAuOF9zZWVkNDNfYmF0Y2hFZmZlY3QwLjc1Lk1OTmNvcnJlY3RlZC5wY2EuY3N2IikgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCkKCmFsbChyb3duYW1lcyhYX3BjYV9tbm4pID09IGNvbG5hbWVzKGVtYnJ5b19zY2UpKQpjb2xkYXRhIDwtIHJlYWRfY3N2KCIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvYmVuY2htYXJrX2VtYnJ5b19wb3BfU29taXRpY19tZXNvZGVybV9lbnIwLjhfc2VlZDQzLmNvbGRhdGEuY3N2IikKY29sRGF0YShlbWJyeW9fc2NlKSA8LSBjb2xkYXRhICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoKSAlPiUgRGF0YUZyYW1lKCkKcmVkdWNlZERpbShlbWJyeW9fc2NlLCAicGNhX2JhdGNoIikgPC0gYXMubWF0cml4KFhfcGNhX21ubikKZW1icnlvX3NjZSA8LSBydW5VTUFQKGVtYnJ5b19zY2UsIGRpbXJlZD0icGNhX2JhdGNoIiwgbmFtZT0idW1hcF9iYXRjaCIpCgppbmRpciA8LSAifi9kYXRhL21pbG9fYmVuY2htYXJrL3N5bnRoZXRpY19kYXRhLyIKcmVzIDwtIHJlYWRfY3N2KCIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvYmVuY2htYXJrX2VtYnJ5b19wb3BfU29taXRpY19tZXNvZGVybV9lbnIwLjhfc2VlZDQzX2JhdGNoRWZmZWN0MC43NS5EQXJlc3VsdHMubWlsby5jc3YiKQplbWJyeW9fc2NlJHByZWQgPC0gcmVzJHByZWQKZW1icnlvX3NjZSR0cnVlIDwtIHJlcyR0cnVlCnBsb3RSZWR1Y2VkRGltKGVtYnJ5b19zY2UsICJ1bWFwX2JhdGNoIiwgY29sb3VyX2J5PSJDb25kaXRpb24xX3Byb2IiLCBwb2ludF9zaXplPTAuMSkKcGxvdFJlZHVjZWREaW0oZW1icnlvX3NjZSwgInVtYXBfYmF0Y2giLCBjb2xvdXJfYnk9InByZWQiLCBwb2ludF9zaXplPTAuMSkKcGxvdFJlZHVjZWREaW0oZW1icnlvX3NjZSwgInVtYXBfYmF0Y2giLCBjb2xvdXJfYnk9InRydWUiLCBwb2ludF9zaXplPTAuMSkKCnJlcyAlPiUKICAub3V0Y29tZV9ieV9wcm9iKGRhX3VwcGVyID0gMC42KSAlPiUKICBtdXRhdGUoRkRSID0gRlAvKFRQK0ZQKSkgCmBgYAoKU2hvdyB3aHkgTWlsbyBoYXMgVFBSPTAgaWYgYmF0Y2ggY292YXJpYXRlIG5vdCBpbmNsdWRlZC4KCmBgYHtyLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD02fQpkYXRhX2lkPSJlbWJyeW8iCnBvcD0iR3V0Igpwb3BfZW5yPSIwLjgiCnNlZWQ9JzQzJwoKIyMgTG9hZCBjb2xkYXRhIGFuZCBQQ0EKb3V0ZGlyIDwtICcvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvc3ludGhldGljX2RhdGEvJwpvdXRwcmVmaXggPC0gc3RyX2MoImJlbmNobWFya18iLCBkYXRhX2lkLCAiX3BvcF8iLCBwb3AsICdfZW5yJywgcG9wX2VuciwgIl9zZWVkIiwgc2VlZCkKY29sZGF0YSA8LSByZWFkX2NzdihwYXN0ZTAob3V0ZGlyLCBvdXRwcmVmaXgsICIuY29sZGF0YS5jc3YiKSkgJT4lIGNvbHVtbl90b19yb3duYW1lcygpClhfcGNhIDwtcmVhZF9jc3Yoc3RyX2Mob3V0ZGlyLCBzdHJfcmVtb3ZlKG91dHByZWZpeCwgIl9jYXBwZWRfbG9naXQuLiIpLCAiX2JhdGNoRWZmZWN0IiwgYmVfc2QsICIucGNhLmNzdiIpKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkgIAoKIyMgRmluZCBEQSBwcm9iYWJpbGl0eSB4IGNlbGwKaz01MApibV9wYXJhbXMgPSBsaXN0KAogIG1pbG8gPSBsaXN0KGs9aykKICApCgoKIyMgQWRkIHJlZHVjZWQgZGltICsgY29sZGF0YSB0byBzY2UKY29sRGF0YShlbWJyeW9fc2NlKSA8LSBEYXRhRnJhbWUoY29sZGF0YSkKcmVkdWNlZERpbShlbWJyeW9fc2NlLCAicGNhX2JhdGNoIikgPC0gYXMubWF0cml4KFhfcGNhKQoKIyMgUnVuIG1pbG8KbWlsb19yZXMgPC0gcnVuX21pbG8oZW1icnlvX3NjZSwgY29uZGl0aW9uX2NvbD0ic3ludGhfbGFiZWxzIiwgc2FtcGxlX2NvbD0nc3ludGhfc2FtcGxlcycsCiAgICAgICAgICAgICAgICAgICAgICAgcmVkdWNlZC5kaW0gPSAicGNhX2JhdGNoIiwgZD0zMCwgaz1ibV9wYXJhbXMkbWlsbyRrKQoKZGVzaWduX2RmIDwtIGFzLnRpYmJsZShjb2xEYXRhKGVtYnJ5b19zY2UpW2MoJ3N5bnRoX3NhbXBsZXMnLCAic3ludGhfbGFiZWxzIildKSAlPiUKICAgIGRpc3RpbmN0KCkgJT4lCiAgICBjb2x1bW5fdG9fcm93bmFtZXMoJ3N5bnRoX3NhbXBsZXMnKQoKcGxvdE5ob29kTUEobWlsb19yZXMkREFyZXMpCgpnZ3Bsb3QobWlsb19yZXMkREFyZXMsIGFlcyhQVmFsdWUpKSArIGdlb21faGlzdG9ncmFtKCkKCm91dCA8LSBtaWxvMm91dHB1dChtaWxvX3JlcyRNaWxvLCBtaWxvX3JlcyREQXJlcywgb3V0X3R5cGUgPSBvdXRfdHlwZSkKaGVhZChuaG9vZENvdW50cyhtaWxvX3JlcyRNaWxvKVssZGVzaWduX2RmJHN5bnRoX2xhYmVscz09IkNvbmRpdGlvbjEiXSkKYGBgCgojIyBOb24tbGluZWFyIGJhdGNoIGVmZmVjdApgYGB7cn0KYWRkX2JhdGNoX2VmZmVjdF9ub25saW5lYXIgPC0gZnVuY3Rpb24oc2NlLCBiYXRjaF9jb2w9InN5bnRoX2JhdGNoZXMiLCB0aGV0YV9kZWc9MjAsIGRpbXM9MToyKXsKICAjIyBTaW11bGF0ZSByb3RhdGlvbiBvZiBmaXJzdCAyIFBDcwogIHRoZXRhPXRoZXRhX2RlZypwaS8xODAKICByb3RNPW1hdHJpeCgwLG5yb3c9MixuY29sPTIpCiAgcm90TVsxLF09Yyhjb3ModGhldGEpLC1zaW4odGhldGEpKQogIHJvdE1bMixdPWMoc2luKHRoZXRhKSxjb3ModGhldGEpKQogIAogIGNlbGxpZHNfc2FtcGxlIDwtIHNwbGl0KHNjZSRjZWxsLCBzY2VbW2JhdGNoX2NvbF1dKQogIFhfcGNhIDwtIHJlZHVjZWREaW0oc2NlLCAicGNhLmNvcnJlY3RlZCIpCiAgWF9wY2FfYmF0Y2ggPC0gWF9wY2EKICAjIyBBcHBseSByb3RhdGlvbiB0byBvbmUgb2YgdGhlIGJhdGNoZXMKICBYX3BjYV9iYXRjaFtjZWxsaWRzX3NhbXBsZVtbbmFtZXMoY2VsbGlkc19zYW1wbGUpWzFdXV0sZGltc10gPC0gdChyb3RNICUqJSB0KFhfcGNhX2JhdGNoW2NlbGxpZHNfc2FtcGxlW1tuYW1lcyhjZWxsaWRzX3NhbXBsZSlbMV1dXSxkaW1zXSkpCiAgcmVkdWNlZERpbShzY2UsICJwY2FfYmF0Y2giKSA8LSBYX3BjYV9iYXRjaAogIHNjZSAgCiAgfQoKY29sZGF0YV9maWxlIDwtIGxpc3QuZmlsZXMoaW5kaXIsIHBhdHRlcm49cGFzdGUwKHBvcCwiLisiLCAiZW5yIixlbnIsIi4rIiwnc2VlZCcsIHNlZWQsICIuY29sZGF0YS5jc3YiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbC5uYW1lcyA9IFRSVUUpCmNvbERhdGEoZW1icnlvX3NjZSkgPC0gcmVhZF9jc3YoY29sZGF0YV9maWxlKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkgJT4lIERhdGFGcmFtZSgpCiAgCmJhdGNoX2NvbD0ic3ludGhfYmF0Y2hlcyIKCmVtYnJ5b19zY2UgPC0gYWRkX2JhdGNoX2VmZmVjdF9ub25saW5lYXIoZW1icnlvX3NjZSwgZGltcz1jKDMsNSksIHRoZXRhX2RlZyA9IDMwKQplbWJyeW9fc2NlIDwtIHJ1blVNQVAoZW1icnlvX3NjZSwgZGltcmVkPSJwY2FfYmF0Y2giLCBuYW1lID0gJ3VtYXBfYmF0Y2gnLCBuX2RpbXJlZD0xOjMwKSAgCgpkYXRhLmZyYW1lKHJlZHVjZWREaW0oZW1icnlvX3NjZSwgInVtYXBfYmF0Y2giKSkgJT4lCiAgICByZW5hbWUoVU1BUDE9WDEsIFVNQVAyPVgyKSAlPiUKICAgIG11dGF0ZSh0cnVlPWVtYnJ5b19zY2Ukc3ludGhfYmF0Y2hlcykgJT4lCiAgICBnZ3Bsb3QoYWVzKFVNQVAxLCBVTUFQMiwgY29sb3I9dHJ1ZSkpICsKICAgIGdlb21fcG9pbnQoc2l6ZT0wLjEpICsKICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChuYW1lPSJCYXRjaCIsIG9wdGlvbj0iY2l2aWRpcyIpICsKICAgICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xOCkgKwogICAgICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0yKSkpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpCgpkYXRhLmZyYW1lKHJlZHVjZWREaW0oZW1icnlvX3NjZSwgIlVNQVAiKSkgJT4lCiAgICByZW5hbWUoVU1BUDE9WDEsIFVNQVAyPVgyKSAlPiUKICAgIG11dGF0ZSh0cnVlPWVtYnJ5b19zY2Ukc3ludGhfYmF0Y2hlcykgJT4lCiAgICBnZ3Bsb3QoYWVzKFVNQVAxLCBVTUFQMiwgY29sb3I9dHJ1ZSkpICsKICAgIGdlb21fcG9pbnQoc2l6ZT0wLjEpICsKICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChuYW1lPSJCYXRjaCIsIG9wdGlvbj0iY2l2aWRpcyIpICsKICAgICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xOCkgKwogICAgICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0yKSkpICsKICAgICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpCgoKIyBiZV9zY2VfbHMgPC0gbGFwcGx5KGMoJzAnLCIwLjI1IiwgIjAuNSIsICIwLjc1IiwgIjEiKSwgZnVuY3Rpb24oeCkgcmVhZF9pbnB1dF9kYXRhKGVtYnJ5b19zY2UsIGluZGlyLCBwb3AsIGVuciwgc2VlZCwgeCwgcnVuX3VtYXAgPSBGQUxTRSkpCgpgYGAKCk1ha2Ugbm9uLWxpbmVhciBiYXRjaCBlZmZlY3QgZm9yIGFsbCBwb3B1bGF0aW9ucwoKYGBge3J9CiMjIFNpbXVsYXRlIGJhdGNoIGVmZmVjdHMgb2YgZGlmZmVyZW50IG1hZ25pdHVkZQpzYXZlX25vbmxpbmVhcl9iZSA8LSBmdW5jdGlvbihzY2UsIHBvcCwgcG9wX2Vuciwgc2VlZCl7CiAgIyMgTG9hZCBjb2xkYXRhIGFuZCBQQ0EKICBvdXRkaXIgPC0gJy9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8nCiAgb3V0cHJlZml4IDwtIHN0cl9jKCJiZW5jaG1hcmtfZW1icnlvX3BvcF8iLCBwb3AsICdfZW5yJywgcG9wX2VuciwgIl9zZWVkIiwgc2VlZCkKICBjb2xkYXRhIDwtIHJlYWRfY3N2KHBhc3RlMChvdXRkaXIsIG91dHByZWZpeCwgIi5jb2xkYXRhLmNzdiIpKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkKICAjIyBBZGQgcmVkdWNlZCBkaW0gKyBjb2xkYXRhIHRvIHNjZQogIGNvbERhdGEoc2NlKSA8LSBEYXRhRnJhbWUoY29sZGF0YSkKICAKICBzZXQuc2VlZChzZWVkKQogIHNjZV9iZSA8LSBhZGRfYmF0Y2hfZWZmZWN0X25vbmxpbmVhcihlbWJyeW9fc2NlLCBkaW1zPWMoMyw1KSwgdGhldGFfZGVnID0gMzApCiAgWF9wY2EgPC0gcmVkdWNlZERpbShzY2VfYmUsICJwY2FfYmF0Y2giKQogICMjIFNhdmUgcmVkdWNlZCBkaW1zCiAgd3JpdGVfY3N2KGFzLmRhdGEuZnJhbWUoWF9wY2EpICU+JSByb3duYW1lc190b19jb2x1bW4oKSwgc3RyX2Mob3V0ZGlyLCBvdXRwcmVmaXgsICJfYmF0Y2hFZmZlY3ROb25MaW5lYXIzMC5wY2EuY3N2IikpCiAgfQoKcG9wcyA8LSB1bmlxdWUob3V0X21ldGFfZGYkcG9wKQpwb3BfZW5ycyA8LSB1bmlxdWUob3V0X21ldGFfZGYkZW5yKQpzZWVkcyA8LSB1bmlxdWUob3V0X21ldGFfZGYkc2VlZCkKCmZvciAocG9wIGluIHBvcHMpIHsKICBmb3IgKHBvcF9lbnIgaW4gcG9wX2VucnNbMTozXSkgewogICAgZm9yIChzZWVkIGluIHNlZWRzKSB7CiAgICAgIHNhdmVfbm9ubGluZWFyX2JlKGVtYnJ5b19zY2UsIHBvcCwgcG9wX2Vuciwgc2VlZCkKICAgIH0KICB9Cn0KCmBgYAoKClJ1bm5pbmcgaW4gYHJ1bl9EQV9ub25saW5lYXIuUmAuIAoKUmVhZCBhbGwgcmVzdWx0cwoKYGBge3J9Cm91dGRpciA8LSAiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrLyIKcmVzX2ZpbGVzIDwtIGxpc3QuZmlsZXMob3V0ZGlyLCBwYXR0ZXJuPSJOb25MaW5lYXIuK0RBcmVzdWx0cy4rLmNzdiIpCnJlc19maWxlc19mdWxsIDwtIGxpc3QuZmlsZXMob3V0ZGlyLCBwYXR0ZXJuPSJOb25MaW5lYXIuK0RBcmVzdWx0cy4rLmNzdiIsIGZ1bGwubmFtZXMgPSBUUlVFKQoKIyMgTWFrZSBkYXRhIGZyYW1lIHcgYmVuY2htYXJrIHBhcmFtZXRlcnMKbm9ubF9vdXRfbWV0YV9kZiA8LSBkYXRhLmZyYW1lKGZpbGVfaWQgPSBzdHJfcmVtb3ZlX2FsbChyZXNfZmlsZXMsICJiZW5jaG1hcmtfZW1icnlvX3BvcF98LmNzdiIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiLkRBcmVzdWx0cy4iLCBpbnRvPWMoImZpbGVfaWQiLCAibWV0aG9kIikpICU+JQogIHNlcGFyYXRlKGNvbCA9IGZpbGVfaWQsIHNlcCA9ICJfZW5yIiwgaW50bz1jKCJwb3AiLCAiZmlsZV9pZCIpKSAlPiUKICBzZXBhcmF0ZShjb2wgPSBmaWxlX2lkLCBzZXAgPSAiXyIsIGludG89YygiZW5yIiwgInNlZWQiLCAiYmF0Y2hFZmZlY3QiKSkgJT4lCiAgbXV0YXRlKHNlZWQ9c3RyX3JlbW92ZShzZWVkLCAic2VlZCIpLCBiYXRjaEVmZmVjdD1zdHJfcmVtb3ZlKGJhdGNoRWZmZWN0LCAiYmF0Y2hFZmZlY3QiKSkKCiMjIExvYWQgcmVzdWx0cwpub25sX291dGNvbWVfZGYgPC0gbGFwcGx5KHNlcV9hbG9uZyhyZXNfZmlsZXNfZnVsbCksIGZ1bmN0aW9uKGkpeyAKICBwcmludChwYXN0ZSgiT3V0Y29tZSBuby4gIiwgaSkpCiAgYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KHJlc19maWxlc19mdWxsW2ldKSAlPiUKICAgICAgLm91dGNvbWVfYnlfcHJvYihkYV91cHBlciA9IDAuNikgJT4lCiAgICAgIG11dGF0ZShEQV90aHJlc2g9MC42KSAlPiUKICAgICAgdW5ncm91cCgpICU+JQogICAgICBkcGx5cjo6c2VsZWN0KC0gbWV0aG9kKSAlPiUKICAgICAgYmluZF9jb2xzKG5vbmxfb3V0X21ldGFfZGZbaSxdKSAKICBwb3BfZW5yIDwtIGFzLm51bWVyaWMobm9ubF9vdXRfbWV0YV9kZltpLCJlbnIiXSkKICBiZW5jaG1hcmtfZGYKICB9KSAlPiUKICBwdXJycjo6cmVkdWNlKGJpbmRfcm93cykKCm5vbmxfb3V0Y29tZV9kZiAKYGBgCmBgYHtyfQpwbF9kZiA8LSBub25sX291dGNvbWVfZGYgJT4lCiAgZmlsdGVyKGVuciA+IDAuNikgJT4lCiAgbXV0YXRlKEZEUiA9IEZQLyhUUCtGUCkpICU+JQogIG11dGF0ZShUUFI9aWZlbHNlKGlzLm5hbihUUFIpLCAwLCBUUFIpLAogICAgICAgICBGUFI9aWZlbHNlKGlzLm5hbihGUFIpLCAwLCBGUFIpLAogICAgICAgICBGRFI9aWZlbHNlKGlzLm5hbihGRFIpLCAwLCBGRFIpLAogICAgICAgICBQcmVjaXNpb249aWZlbHNlKGlzLm5hbihQcmVjaXNpb24pLCAwLCBQcmVjaXNpb24pKSAlPiUKICBtdXRhdGUocG9wPXN0cl9yZXBsYWNlKHBvcCwgIl8iLCAiICIpKSAKCnBsX2RmICU+JQogIGdncGxvdChhZXMocG9wLCBUUFIpKSArIAogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC44LCBsaW5ldHlwZT0yKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTYpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iRGFyazIiKSArCiAgZmFjZXRfZ3JpZChlbnJ+LiwgbGFiZWxsZXIgPSBlbnJfbGFiZWxsZXIpICsKcGxfZGYgJT4lCiAgZ2dwbG90KGFlcyhwb3AsIEZEUikpICsgCiAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbShhbHBoYT0wLjUpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjEsIGxpbmV0eXBlPTIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsKICBmYWNldF9ncmlkKGVucn4uLCBsYWJlbGxlciA9IGVucl9sYWJlbGxlcikgKwpwbG90X2xheW91dChndWlkZXM9J2NvbGxlY3QnKSAKYGBgCmBgYHtyfQpsaW5fYmUgPC0gb3V0Y29tZV9kZiAlPiUKICBmaWx0ZXIobWV0aG9kPT0ibWlsb19iYXRjaCIgJiBlbnIgJWluJSBjKDAuNywgMC44KSAmIERBX3RocmVzaD09MC42KQoKYmluZF9yb3dzKAogIG11dGF0ZShsaW5fYmUsIGNsYXNzPSJMaW5lYXIgYmF0Y2ggZWZmZWN0IiksCiAgbXV0YXRlKG5vbmxfb3V0Y29tZV9kZiwgY2xhc3M9Ik5vbiBMaW5lYXJcbiBiYXRjaCBlZmZlY3QiKSAlPiUKICAgIGZpbHRlcihlbnIgPiAwLjYpICU+JQogICAgbXV0YXRlKGVucj1hcy5udW1lcmljKGVuciksIHNlZWQ9YXMubnVtZXJpYyhzZWVkKSwgYmF0Y2hFZmZlY3Q9YXMubnVtZXJpYyhzdHJfcmVtb3ZlKGJhdGNoRWZmZWN0LCAiTm9uTGluZWFyIikpKSAKICApICU+JQogIGdncGxvdChhZXMoYXMuZmFjdG9yKGJhdGNoRWZmZWN0KSwgVFBSLCBjb2xvcj1tZXRob2QpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oYWxwaGE9MC41KSArCiAgZmFjZXRfZ3JpZChlbnJ+Y2xhc3MsIHNjYWxlcz0iZnJlZSIsIHNwYWNlPSJmcmVlIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9bWV0aG9kX2NvbG9yc1tbNF1dLCBsYWJlbHM9c2V0TmFtZXMobWV0aG9kX2xhYmVscywgbWV0aG9kX25hbWVzKSkgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZT0xNikgKwogIHhsYWIoIkJhdGNoIGVmZmVjdCBtYWduaXR1ZGUiKQpgYGAKCgoKCjwhLS0gIyMgQ3lkYXIgb24gc2ltcGxlIHRyYWplY3RvcnkgLS0+Cgo8IS0tIFBpY2sgcmFkaXVzIHBhcmFtZXRlciBmb3IgZGlmZmVyZW50IGRhdGFzZXRzOiBGb3IgZWFjaCBoeXBlcnNwaGVyZSBjZW50cmVkIG9uIGEgY2VsbCwgdGhlIHJhZGl1cyAtLT4KPCEtLSByZXF1aXJlZCB0byBpbmNsdWRlIGEgY2VydGFpbiBudW1iZXIgb2YgbmVhcmVzdCBuZWlnaGJvdXJzIGlzIGNvbXB1dGVkLiAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIHNhbXBsZV9jb2wgPSAic3ludGhfc2FtcGxlcyIgLS0+CjwhLS0gZD0zMCAtLT4KPCEtLSBzY2UgPC0gcmVhZFJEUygiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2NsdXN0ZXJfZGF0YV9ibS5SRFMiKSAtLT4KPCEtLSBzYW1wbGVfbHMgPC0gc3BsaXQoMTpuY29sKHNjZSksIHNjZVtbc2FtcGxlX2NvbF1dKSAtLT4KPCEtLSBwcm9jZXNzZWQuZXhwcnMgPC0gbGFwcGx5KHNhbXBsZV9scywgZnVuY3Rpb24ocykgcmVkdWNlZERpbShzY2VbLHNdLCAicGNhLmNvcnJlY3RlZCIpWywxOmRdKSAtLT4KPCEtLSBjZCA8LSBwcmVwYXJlQ2VsbERhdGEocHJvY2Vzc2VkLmV4cHJzKSAtLT4KPCEtLSBib3hwbG90KG5laWdoYm9yRGlzdGFuY2VzKGNkLCBuZWlnaGJvcnM9NTAsIGFzLnRvbD1UUlVFKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gc2FtcGxlX2NvbCA9ICJzeW50aF9zYW1wbGVzIiAtLT4KPCEtLSBkPTMwIC0tPgo8IS0tIHNjZSA8LSByZWFkUkRTKCIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvYnJhbmNoaW5nX2RhdGFfYm0uUkRTIikgLS0+CjwhLS0gc2FtcGxlX2xzIDwtIHNwbGl0KDE6bmNvbChzY2UpLCBzY2VbW3NhbXBsZV9jb2xdXSkgLS0+CjwhLS0gcHJvY2Vzc2VkLmV4cHJzIDwtIGxhcHBseShzYW1wbGVfbHMsIGZ1bmN0aW9uKHMpIHJlZHVjZWREaW0oc2NlWyxzXSwgInBjYS5jb3JyZWN0ZWQiKVssMTpkXSkgLS0+CjwhLS0gY2QgPC0gcHJlcGFyZUNlbGxEYXRhKHByb2Nlc3NlZC5leHBycykgLS0+CjwhLS0gYm94cGxvdChuZWlnaGJvckRpc3RhbmNlcyhjZCwgbmVpZ2hib3JzPTUwLCBhcy50b2w9VFJVRSkpIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIHNhbXBsZV9jb2wgPSAic3ludGhfc2FtcGxlcyIgLS0+CjwhLS0gZD0zMCAtLT4KPCEtLSBzY2UgPC0gcmVhZFJEUygiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2xpbmVhcl9kYXRhX2JtLlJEUyIpIC0tPgo8IS0tIHNhbXBsZV9scyA8LSBzcGxpdCgxOm5jb2woc2NlKSwgc2NlW1tzYW1wbGVfY29sXV0pIC0tPgo8IS0tIHByb2Nlc3NlZC5leHBycyA8LSBsYXBwbHkoc2FtcGxlX2xzLCBmdW5jdGlvbihzKSByZWR1Y2VkRGltKHNjZVssc10sICJwY2EuY29ycmVjdGVkIilbLDE6ZF0pIC0tPgo8IS0tIGNkIDwtIHByZXBhcmVDZWxsRGF0YShwcm9jZXNzZWQuZXhwcnMpIC0tPgo8IS0tIGJveHBsb3QobmVpZ2hib3JEaXN0YW5jZXMoY2QsIG5laWdoYm9ycz01MCwgYXMudG9sPVRSVUUpKSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIHNhbXBsZV9jb2wgPSAic3ludGhfc2FtcGxlcyIgLS0+CjwhLS0gZD0zMCAtLT4KPCEtLSBzY2UgPC0gZW1icnlvX3NjZSAtLT4KPCEtLSBzYW1wbGVfbHMgPC0gc3BsaXQoMTpuY29sKHNjZSksIHNjZVtbc2FtcGxlX2NvbF1dKSAtLT4KPCEtLSBwcm9jZXNzZWQuZXhwcnMgPC0gbGFwcGx5KHNhbXBsZV9scywgZnVuY3Rpb24ocykgcmVkdWNlZERpbShzY2VbLHNdLCAicGNhLmNvcnJlY3RlZCIpWywxOmRdKSAtLT4KPCEtLSBjZCA8LSBwcmVwYXJlQ2VsbERhdGEocHJvY2Vzc2VkLmV4cHJzKSAtLT4KPCEtLSBib3hwbG90KG5laWdoYm9yRGlzdGFuY2VzKGNkLCBuZWlnaGJvcnM9NTAsIGFzLnRvbD1UUlVFKSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gdG9sX2RhdGFzZXQgPC0gbGlzdChjbHVzdGVyPTAuOCwgYnJhbmNoaW5nPTYsIGxpbmVhcj02LCBlbWJyeW89MSkgLS0+CjwhLS0gYGBgIC0tPgoKCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBzY2UgPC0gcmVhZFJEUygiL25mcy90ZWFtMjA1L2VkNi9kYXRhL21pbG9fYmVuY2htYXJrL2xpbmVhcl9kYXRhX2JtLlJEUyIpIC0tPgo8IS0tIGRhdGFfaWQgPC0gImxpbmVhciIgLS0+CjwhLS0gcG9wIDwtICJNMSIgLS0+CjwhLS0gcG9wX2VuciA8LSAwLjkgLS0+CjwhLS0gc2VlZCA8LSAnNDMnIC0tPgo8IS0tIG1ubl9jb3JyZWN0IDwtICJubyIgLS0+CjwhLS0gYmVfc2QgPC0gJzAnIC0tPgoKPCEtLSAjIyBMb2FkIGNvbGRhdGEgYW5kIFBDQSAtLT4KPCEtLSBvdXRkaXIgPC0gJy9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8nIC0tPgo8IS0tIG91dHByZWZpeCA8LSBzdHJfYygiYmVuY2htYXJrXyIsIGRhdGFfaWQsICJfcG9wXyIsIHBvcCwgJ19lbnInLCBwb3BfZW5yLCAiX3NlZWQiLCBzZWVkKSAtLT4KPCEtLSBjb2xkYXRhIDwtIHJlYWRfY3N2KHBhc3RlMChvdXRkaXIsIG91dHByZWZpeCwgIi5jb2xkYXRhLmNzdiIpKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkgLS0+CjwhLS0gaWYgKG1ubl9jb3JyZWN0PT0ibm8iKSB7IC0tPgo8IS0tICAgWF9wY2EgPC1yZWFkX2NzdihzdHJfYyhvdXRkaXIsIG91dHByZWZpeCwgIl9iYXRjaEVmZmVjdCIsIGJlX3NkLCAiLnBjYS5jc3YiKSkgJT4lIGNvbHVtbl90b19yb3duYW1lcygpICAgLS0+CjwhLS0gfSBlbHNlIHsgLS0+CjwhLS0gICBYX3BjYSA8LXJlYWRfY3N2KHN0cl9jKG91dGRpciwgb3V0cHJlZml4LCAiX2JhdGNoRWZmZWN0IiwgYmVfc2QsICIuTU5OY29ycmVjdGVkLnBjYS5jc3YiKSkgJT4lIGNvbHVtbl90b19yb3duYW1lcygpIC0tPgo8IS0tIH0gLS0+CjwhLS0gIyMgQWRkIHJlZHVjZWQgZGltICsgY29sZGF0YSB0byBzY2UgLS0+CjwhLS0gY29sRGF0YShzY2UpIDwtIERhdGFGcmFtZShjb2xkYXRhKSAtLT4KPCEtLSByZWR1Y2VkRGltKHNjZSwgInBjYV9iYXRjaCIpIDwtIGFzLm1hdHJpeChYX3BjYSkgLS0+CjwhLS0gcGxvdFJlZHVjZWREaW0oc2NlLCAiVU1BUCIsY29sb3VyX2J5PSJzeW50aF9sYWJlbHMiKSAtLT4KPCEtLSBwbG90UmVkdWNlZERpbShzY2UsICJVTUFQIixjb2xvdXJfYnk9IkNvbmRpdGlvbjFfcHJvYiIpIC0tPgoKPCEtLSBjeWRhcl9yZXMgPC0gcnVuREEoc2NlLCBjb2xkYXRhLCBYX3BjYSwgImN5ZGFyIiwgb3V0X3R5cGUgPSAibGFiZWxzIixkID0gMzAsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgcGFyYW1zPWxpc3QoY3lkYXI9bGlzdCh0b2w9dG9sX2RhdGFzZXRbW2RhdGFfaWRdXSwgZG93bnNhbXBsZT0zKSkpIC0tPgo8IS0tIGRmIDwtIC5vdXRjb21lX2J5X3Byb2IoY3lkYXJfcmVzLCAwLjYpICAtLT4KCjwhLS0gZGYgLS0+Cgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBzY2UgPC0gZW1icnlvX3NjZSAtLT4KPCEtLSBkYXRhX2lkIDwtICJlbWJyeW8iIC0tPgo8IS0tIHBvcCA8LSAiRXJ5dGhyb2lkMiIgLS0+CjwhLS0gcG9wX2VuciA8LSAwLjkgLS0+CjwhLS0gc2VlZCA8LSAnNDMnIC0tPgo8IS0tIG1ubl9jb3JyZWN0IDwtICJubyIgLS0+CjwhLS0gYmVfc2QgPC0gJzAnIC0tPgoKPCEtLSAjIyBMb2FkIGNvbGRhdGEgYW5kIFBDQSAtLT4KPCEtLSBvdXRkaXIgPC0gJy9uZnMvdGVhbTIwNS9lZDYvZGF0YS9taWxvX2JlbmNobWFyay9zeW50aGV0aWNfZGF0YS8nIC0tPgo8IS0tIG91dHByZWZpeCA8LSBzdHJfYygiYmVuY2htYXJrXyIsIGRhdGFfaWQsICJfcG9wXyIsIHBvcCwgJ19lbnInLCBwb3BfZW5yLCAiX3NlZWQiLCBzZWVkKSAtLT4KPCEtLSBjb2xkYXRhIDwtIHJlYWRfY3N2KHBhc3RlMChvdXRkaXIsIG91dHByZWZpeCwgIi5jb2xkYXRhLmNzdiIpKSAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCkgLS0+CjwhLS0gaWYgKG1ubl9jb3JyZWN0PT0ibm8iKSB7IC0tPgo8IS0tICAgWF9wY2EgPC1yZWFkX2NzdihzdHJfYyhvdXRkaXIsIG91dHByZWZpeCwgIl9iYXRjaEVmZmVjdCIsIGJlX3NkLCAiLnBjYS5jc3YiKSkgJT4lIGNvbHVtbl90b19yb3duYW1lcygpICAgLS0+CjwhLS0gfSBlbHNlIHsgLS0+CjwhLS0gICBYX3BjYSA8LXJlYWRfY3N2KHN0cl9jKG91dGRpciwgb3V0cHJlZml4LCAiX2JhdGNoRWZmZWN0IiwgYmVfc2QsICIuTU5OY29ycmVjdGVkLnBjYS5jc3YiKSkgJT4lIGNvbHVtbl90b19yb3duYW1lcygpIC0tPgo8IS0tIH0gLS0+CjwhLS0gIyMgQWRkIHJlZHVjZWQgZGltICsgY29sZGF0YSB0byBzY2UgLS0+CjwhLS0gY29sRGF0YShzY2UpIDwtIERhdGFGcmFtZShjb2xkYXRhKSAtLT4KPCEtLSByZWR1Y2VkRGltKHNjZSwgInBjYV9iYXRjaCIpIDwtIGFzLm1hdHJpeChYX3BjYSkgLS0+CjwhLS0gcGxvdFJlZHVjZWREaW0oc2NlLCAiVU1BUCIsY29sb3VyX2J5PSJzeW50aF9sYWJlbHMiKSAtLT4KPCEtLSBwbG90UmVkdWNlZERpbShzY2UsICJVTUFQIixjb2xvdXJfYnk9IkNvbmRpdGlvbjFfcHJvYiIpIC0tPgoKPCEtLSBjeWRhcl9yZXMgPC0gcnVuREEoc2NlLCBjb2xkYXRhLCBYX3BjYSwgImN5ZGFyIiwgb3V0X3R5cGUgPSAibGFiZWxzIixkID0gMzAsIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgcGFyYW1zPWxpc3QoY3lkYXI9bGlzdCh0b2w9dG9sX2RhdGFzZXRbW2RhdGFfaWRdXSwgZG93bnNhbXBsZT0zKSkpIC0tPgo8IS0tIGRmIDwtIC5vdXRjb21lX2J5X3Byb2IoY3lkYXJfcmVzLCAwLjYpICAtLT4KCjwhLS0gZGYgLS0+CgoKPCEtLSBgYGAgLS0+CgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tIHNpbS5kZXNpZ24gPC0gbW9kZWwubWF0cml4KGRlc2lnbiwgZGF0YT1kZXNpZ25fZGYpW2NvbG5hbWVzKGNkLmRnZSksXSAtLT4KPCEtLSBzaW0uZGdlIDwtIGVzdGltYXRlRGlzcChjZC5kZ2UsIHNpbS5kZXNpZ24pIC0tPgo8IS0tIHNpbS5maXQgPC0gZ2xtUUxGaXQoc2ltLmRnZSwgc2ltLmRlc2lnbikgLS0+CjwhLS0gc2ltLnJlcyA8LSBnbG1RTEZUZXN0KHNpbS5maXQsIGNvZWY9MikgLS0+Cgo8IS0tICMgY29udHJvbCB0aGUgc3BhdGlhbCBGRFIgLS0+CjwhLS0gY3lkYXIucmVzIDwtIHNpbS5yZXMkdGFibGUgLS0+CjwhLS0gY3lkYXIucmVzJFNwYXRpYWxGRFIgPC0gc3BhdGlhbEZEUihpbnRlbnNpdGllcyhjZCksIHNpbS5yZXMkdGFibGUkUFZhbHVlKSAtLT4KPCEtLSBib3hwbG90KHNpbS5kZ2UkY291bnRzKSAtLT4KPCEtLSBoaXN0KGN5ZGFyLnJlcyRQVmFsdWUpIC0tPgoKPCEtLSBjeWRhci5yZXMkU3BhdGlhbEZEUiA8IDAuMSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gY29sRGF0YShzaW1fdHJhamVjdG9yeSRTQ0UpIDwtIERhdGFGcmFtZShzaW1fdHJhamVjdG9yeSRtZXRhKSAtLT4KPCEtLSBwbG90UENBKHNpbV90cmFqZWN0b3J5JFNDRSwgY29sb3VyX2J5PSJDb25kaXRpb24iKSAtLT4KPCEtLSBwbG90UmVkdWNlZERpbShzY2UsICJwY2EuY29ycmVjdGVkIixjb2xvdXJfYnk9InN5bnRoX2xhYmVscyIpIC0tPgo8IS0tIHBsb3RSZWR1Y2VkRGltKHNjZSwgIlVNQVAiLGNvbG91cl9ieT0iQ29uZGl0aW9uMV9wcm9iIikgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBUcnkgZG93bnNhbXBsaW5nIG9uZSBvZiB0aGUgMiBjb25kaXRpb25zIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gQzFfY2VsbHMgPC0gY29sbmFtZXMoc2NlKVtzY2Ukc3ludGhfbGFiZWxzPT0iQ29uZGl0aW9uMSJdIC0tPgo8IS0tIEMyX2NlbGxzIDwtIGNvbG5hbWVzKHNjZSlbc2NlJHN5bnRoX2xhYmVscz09IkNvbmRpdGlvbjIiXSAtLT4KPCEtLSBzbXBfQzIgPC0gc2FtcGxlKEMyX2NlbGxzLCBzaXplID0gbGVuZ3RoKEMyX2NlbGxzKSAqIDEpIC0tPgoKPCEtLSBzY2VbLGMoQzFfY2VsbHMsIEMyX2NlbGxzKV0gIC0tPgo8IS0tIHNjZSAtLT4KPCEtLSB0YWJsZShydW5fY3lkYXIoc2NlWyxjKEMxX2NlbGxzLCBDMl9jZWxscyldLCB0b2wgPSAzLjAsIGQ9MzApJERBcmVzJFNwYXRpYWxGRFIgPCAwLjEpIC0tPgo8IS0tIGBgYCAtLT4KPCEtLSBgYGB7cn0gLS0+CjwhLS0gYmVuY2htYXJrX2RmIDwtIHJlYWRfY3N2KCIvbmZzL3RlYW0yMDUvZWQ2L2RhdGEvbWlsb19iZW5jaG1hcmsvYmVuY2htYXJrX2VtYnJ5b19wb3BfRXJ5dGhyb2lkMl9lbnIwLjlfc2VlZDQzX2JhdGNoRWZmZWN0MC5EQXJlc3VsdHMuZGFzZXEuY3N2IikgIC0tPgoKPCEtLSAub3V0Y29tZV9ieV9wcm9iKGJlbmNobWFya19kZiwgMC42KSAtLT4KCgo8IS0tIC5vdXRjb21lX2J5X3Byb2IoYmVuY2htYXJrX2RmLCAwLjYpIC0tPgo8IS0tIGBgYCAtLT4KCiMjIExvdXZhaW4gb24gaXRlcmF0aXZlIHN1YmNsdXN0ZXJpbmcKCmBgYHtyfQpwbG90VU1BUChlbWJyeW9fc2NlLCBjb2xvdXJfYnk9IkNvbmRpdGlvbjFfcHJvYiIpCmBgYAoKU3ViY2x1c3RlciBhbGwgY2VsbHR5cGUgcG9wdWxhdGlvbnMgKHRoZXJlIGlzIGEgY2F2ZWF0IGhlcmUgdGhhdCBJIGFtIG5vdCByZWNhbGN1bGF0aW5nIHRoZSBQQ0Egc3BhY2UgZm9yIGFsbCBzdWJzZXRzLCBidXQgaXQgc2hvdWxkIGJyaW5nIGhvbWUgdGhlIG1lc3NhZ2UgcmVnYXJkbGVzcykKCmBgYHtyfQplbWJyeW9fc2NlJHN1YmNsdXN0ZXIgPC0gTkEKaz0xNQoKZm9yIChwb3AgaW4gdW5pcXVlKGVtYnJ5b19zY2UkY2VsbHR5cGUpKSB7CiAgcG9wX3NjZSA8LSBlbWJyeW9fc2NlWyxlbWJyeW9fc2NlJGNlbGx0eXBlPT1wb3BdCiAgWF9yZWRfZGltIDwtIHJlZHVjZWREaW0ocG9wX3NjZSwgInBjYS5jb3JyZWN0ZWQiKQogIHNjZS5ncmFwaCA8LSBidWlsZEtOTkdyYXBoKHQoWF9yZWRfZGltKSwgaz1rKQogIGxvdXZhaW4uY2x1c3QgPC0gY2x1c3Rlcl9sb3V2YWluKHNjZS5ncmFwaCkKICBsb3V2YWluLmNsdXN0LmlkcyA8LSBtZW1iZXJzaGlwKGxvdXZhaW4uY2x1c3QpCiAgcG9wX3NjZSRzdWJjbHVzdGVyIDwtIHBhc3RlKHBvcCwgYXMuY2hhcmFjdGVyKGxvdXZhaW4uY2x1c3QuaWRzKSwgc2VwPSJfIikKICBzdWJjbHVzdGVycyA8LSBzZXROYW1lcyhwb3Bfc2NlJHN1YmNsdXN0ZXIsIGNvbG5hbWVzKHBvcF9zY2UpKQogIGNvbERhdGEoZW1icnlvX3NjZSlbInN1YmNsdXN0ZXIiXVtuYW1lcyhzdWJjbHVzdGVycyksXSA8LSBzdWJjbHVzdGVycwogIH0KCiMgcG9wX3NjZSA8LSBydW5VTUFQKHBvcF9zY2UsIGRpbXJlZD0icGNhLmNvcnJlY3RlZCIpCnN1YmNsdXN0ZXJzX3VtYXAgPC0gZGF0YS5mcmFtZShyZWR1Y2VkRGltKGVtYnJ5b19zY2UsICJVTUFQIikpICU+JQogIG11dGF0ZShzdWJjbHVzdGVyPWVtYnJ5b19zY2Ukc3ViY2x1c3RlcikgJT4lCiAgbXV0YXRlKHN1YmNsdXN0ZXI9ZmFjdG9yKHN1YmNsdXN0ZXIsIGxldmVscz1zYW1wbGUodW5pcXVlKHN1YmNsdXN0ZXIpKSkpICU+JQogIGdncGxvdChhZXMoWDEsIFgyLCBjb2xvcj1zdWJjbHVzdGVyKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEpICsKICBndWlkZXMoY29sb3I9Im5vbmUiKSArCiAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE4KQpgYGAKCgpNYWtlIHNpbXVsYXRlZCBsYWJlbHMgCmBgYHtyfQplbWJyeW9fc2NlIDwtIGFkZF9zeW50aGV0aWNfbGFiZWxzX3BvcChlbWJyeW9fc2NlLCBwb3A9IlNvbWl0aWMgbWVzb2Rlcm0iLCBwb3BfY29sdW1uID0gImNlbGx0eXBlIiwgc2VlZD00MiwgcG9wX2Vucj0wLjgpCnRydWVfbGFiZWxzIDwtIGlmZWxzZShlbWJyeW9fc2NlJENvbmRpdGlvbjJfcHJvYiA8IDAuNCwgIk5lZ0xGQyIsIGlmZWxzZShlbWJyeW9fc2NlJENvbmRpdGlvbjJfcHJvYiA+IDAuNiwgIlBvc0xGQyIsICJOb3REQSIpKQpjb2xEYXRhKGVtYnJ5b19zY2UpW1sidHJ1ZV9sYWJlbHMiXV0gPC0gdHJ1ZV9sYWJlbHMKYGBgCgpUZXN0aW5nIGZvciBEQSB3aXRoIEdMTSBvbiBzdWJjbHVzdGVycwoKYGBge3J9CmNvbmRpdGlvbl9jb2wgPSAic3ludGhfbGFiZWxzIgpzYW1wbGVfY29sID0gInN5bnRoX3NhbXBsZXMiCnNjZSA8LSBlbWJyeW9fc2NlCgojIyBNYWtlIGRlc2lnbiBtYXRyaXgKZGVzaWduX2RmIDwtIGFzLnRpYmJsZShjb2xEYXRhKHNjZSlbYyhzYW1wbGVfY29sLCBjb25kaXRpb25fY29sKV0pICU+JQogICAgZGlzdGluY3QoKSAlPiUKICAgIHJlbmFtZShzYW1wbGU9c2FtcGxlX2NvbCkKZGVzaWduIDwtIGZvcm11bGEocGFzdGUoJ0ZyZXEgficsIGNvbmRpdGlvbl9jb2wsICIrIG9mZnNldChsb2coTl9zKSkiLCBjb2xsYXBzZSA9ICcgJykpICAKCiMjIFRlc3QgREEgaW4gc3ViY2x1c3RlcnMKY29uZGl0aW9uX3ZlYyA8LSBjb2xEYXRhKGVtYnJ5b19zY2UpW1tjb25kaXRpb25fY29sXV0Kc2FtcGxlX2xhYmVscyA8LSBjb2xEYXRhKGVtYnJ5b19zY2UpW1tzYW1wbGVfY29sXV0KY2x1c3QuZGYgPC0gZGF0YS5mcmFtZSgiY2VsbF9pZCI9Y29sbmFtZXMoZW1icnlvX3NjZSksICJMb3V2YWluLkNsdXN0Ij1lbWJyeW9fc2NlJHN1YmNsdXN0ZXIpCmNsdXN0LmRmJFNhbXBsZSA8LSBzYW1wbGVfbGFiZWxzCmNsdXN0LmRmJENvbmRpdGlvbiA8LSBjb25kaXRpb25fdmVjCgpsb3V2YWluLmNvdW50IDwtIHRhYmxlKGNsdXN0LmRmJExvdXZhaW4uQ2x1c3QsIGNsdXN0LmRmJFNhbXBsZSkKYXR0cmlidXRlcyhsb3V2YWluLmNvdW50KSRjbGFzcyA8LSAibWF0cml4IgogIApkZiA8LSBtZWx0KGxvdXZhaW4uY291bnQsIHZhcm5hbWVzPWMoImNsdXN0ZXIiLCAic2FtcGxlIiksICB2YWx1ZS5uYW1lPSJGcmVxIikgJT4lCiAgICBtdXRhdGUoY2x1c3Rlcj1mYWN0b3IoY2x1c3RlcikpICU+JQogICAgbGVmdF9qb2luKGRlc2lnbl9kZiwgYnk9InNhbXBsZSIpICU+JQogICAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUKICAgIG11dGF0ZShOX3M9c3VtKEZyZXEpKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIGdyb3VwX2J5KGNsdXN0ZXIpICU+JQogICAgZG8obW9kZWw9Z2xtKGRlc2lnbiwgZGF0YT0uLCBmYW1pbHk9InBvaXNzb24iKSkgCiAgCnJlc19kZiA8LSB0KHNhcHBseShkZiRtb2RlbCwgZnVuY3Rpb24oeCkgc3VtbWFyeSh4KSRjb2VmZmljaWVudHNbbnJvdyhzdW1tYXJ5KHgpJGNvZWZmaWNpZW50cyksXSkpCmNvbG5hbWVzKHJlc19kZikgPC0gYygibG9nRkMiLCJTdGQuIEVycm9yIiwgInogdmFsdWUiLCAgICAiUHZhbCIgKQpsb3V2YWluLnJlcyA8LSBjYmluZChkZiwgcmVzX2RmKSAlPiUKICBtdXRhdGUoRkRSPXAuYWRqdXN0KFB2YWwsIG1ldGhvZCA9ICJCSCIpKQpyb3duYW1lcyhsb3V2YWluLnJlcykgPC0gbG91dmFpbi5yZXMkY2x1c3RlcgogIApjbHVzdC5kZiRsb2dGQyA8LSBsb3V2YWluLnJlc1tjbHVzdC5kZiRMb3V2YWluLkNsdXN0LCAnbG9nRkMnXQpjbHVzdC5kZiRGRFIgPC0gbG91dmFpbi5yZXNbY2x1c3QuZGYkTG91dmFpbi5DbHVzdCwgJ0ZEUiddCmVtYnJ5b19zY2UkcHJlZERBX3N1YmNsdXN0ZXJzIDwtIGxvdXZhaW4yb3V0cHV0KGNsdXN0LmRmLCBvdXRfdHlwZSA9ICJsYWJlbHMiKQoKY2x1c3QuZGYgJT4lCiAgZ2dwbG90KGFlcyhsb2dGQywgLWxvZzEwKEZEUikpKSArIGdlb21fcG9pbnQoKQpgYGAKCmBgYHtyfQojIyBUZXN0IERBIGluIGNlbGwgdHlwZSBjbHVzdGVycwpjbHVzdC5kZiA8LSBkYXRhLmZyYW1lKCJjZWxsX2lkIj1jb2xuYW1lcyhlbWJyeW9fc2NlKSwgIkxvdXZhaW4uQ2x1c3QiPWVtYnJ5b19zY2UkY2VsbHR5cGUpCmNsdXN0LmRmJFNhbXBsZSA8LSBzYW1wbGVfbGFiZWxzCmNsdXN0LmRmJENvbmRpdGlvbiA8LSBjb25kaXRpb25fdmVjCgpsb3V2YWluLmNvdW50IDwtIHRhYmxlKGNsdXN0LmRmJExvdXZhaW4uQ2x1c3QsIGNsdXN0LmRmJFNhbXBsZSkKYXR0cmlidXRlcyhsb3V2YWluLmNvdW50KSRjbGFzcyA8LSAibWF0cml4IgogIApkZiA8LSBtZWx0KGxvdXZhaW4uY291bnQsIHZhcm5hbWVzPWMoImNsdXN0ZXIiLCAic2FtcGxlIiksICB2YWx1ZS5uYW1lPSJGcmVxIikgJT4lCiAgICBtdXRhdGUoY2x1c3Rlcj1mYWN0b3IoY2x1c3RlcikpICU+JQogICAgbGVmdF9qb2luKGRlc2lnbl9kZiwgYnk9InNhbXBsZSIpICU+JQogICAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUKICAgIG11dGF0ZShOX3M9c3VtKEZyZXEpKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIGdyb3VwX2J5KGNsdXN0ZXIpICU+JQogICAgZG8obW9kZWw9Z2xtKGRlc2lnbiwgZGF0YT0uLCBmYW1pbHk9InBvaXNzb24iKSkgCiAgCnJlc19kZiA8LSB0KHNhcHBseShkZiRtb2RlbCwgZnVuY3Rpb24oeCkgc3VtbWFyeSh4KSRjb2VmZmljaWVudHNbbnJvdyhzdW1tYXJ5KHgpJGNvZWZmaWNpZW50cyksXSkpCmNvbG5hbWVzKHJlc19kZikgPC0gYygibG9nRkMiLCJTdGQuIEVycm9yIiwgInogdmFsdWUiLCAgICAiUHZhbCIgKQpsb3V2YWluLnJlcyA8LSBjYmluZChkZiwgcmVzX2RmKSAlPiUKICBtdXRhdGUoRkRSPXAuYWRqdXN0KFB2YWwsIG1ldGhvZCA9ICJCSCIpKQpyb3duYW1lcyhsb3V2YWluLnJlcykgPC0gbG91dmFpbi5yZXMkY2x1c3RlcgogIApjbHVzdC5kZiRsb2dGQyA8LSBsb3V2YWluLnJlc1tjbHVzdC5kZiRMb3V2YWluLkNsdXN0LCAnbG9nRkMnXQpjbHVzdC5kZiRGRFIgPC0gbG91dmFpbi5yZXNbY2x1c3QuZGYkTG91dmFpbi5DbHVzdCwgJ0ZEUiddCmVtYnJ5b19zY2UkcHJlZERBX2NlbGx0eXBlIDwtIGxvdXZhaW4yb3V0cHV0KGNsdXN0LmRmLCBvdXRfdHlwZSA9ICJsYWJlbHMiKQoKY2x1c3QuZGYgJT4lCiAgZ2dwbG90KGFlcyhsb2dGQywgLWxvZzEwKEZEUikpKSArIGdlb21fcG9pbnQoKQpgYGAKCmBgYHtyfQptaWxvX3JlcyA8LSBydW5fbWlsbyhlbWJyeW9fc2NlLCBjb25kaXRpb25fY29sPSJzeW50aF9sYWJlbHMiLCBzYW1wbGVfY29sPSJzeW50aF9zYW1wbGVzIiwgcmVkdWNlZC5kaW0gPSAicGNhLmNvcnJlY3RlZCIsCiAgICAgICAgaz01MCwgZCA9IDMwKQoKCmVtYnJ5b19zY2UkcHJlZERBX21pbG8gPC0gbWlsbzJvdXRwdXQobWlsb19yZXMkTWlsbywgbWlsb19yZXMkREFyZXMsIG91dF90eXBlID0gImxhYmVscyIsIGFscGhhID0gMC4xKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEwfQojIGVtYnJ5b19zY2UkcHJlZERBIDwtIGxvdXZhaW4yb3V0cHV0KGNsdXN0LmRmLCBvdXRfdHlwZSA9ICJsYWJlbHMiKQoKcGxfZGYgPC0gZGF0YS5mcmFtZShyZWR1Y2VkRGltKGVtYnJ5b19zY2UsICJVTUFQIikpICU+JQogIG11dGF0ZShzdWJjbHVzdGVyPWVtYnJ5b19zY2Ukc3ViY2x1c3RlcikgJT4lCiAgbXV0YXRlKHN1YmNsdXN0ZXI9ZmFjdG9yKHN1YmNsdXN0ZXIsIGxldmVscz1zYW1wbGUodW5pcXVlKHN1YmNsdXN0ZXIpKSkpICU+JQogIG11dGF0ZShwcmVkREFfc3ViY2x1c3RlcnM9ZW1icnlvX3NjZSRwcmVkREFfc3ViY2x1c3RlcnMsCiAgICAgICAgIHByZWREQV9jZWxsdHlwZT1lbWJyeW9fc2NlJHByZWREQV9jZWxsdHlwZSwKICAgICAgICAgcHJlZERBX21pbG89ZW1icnlvX3NjZSRwcmVkREFfbWlsbywKICAgICAgICAgdHJ1ZURBID0gZW1icnlvX3NjZSR0cnVlX2xhYmVscykgCgp0cnVlX3BsIDwtIHBsX2RmICU+JQogIGdncGxvdChhZXMoWDEsIFgyLCBjb2xvcj10cnVlREEpKSArCiAgZ2VvbV9wb2ludChzaXplPTAuMSkgKwogIHhsYWIoIlVNQVAxIikgKyB5bGFiKCJVTUFQMiIpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZT0xOCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YyhOb3REQT0iZ3JleSIsIFBvc0xGQz0iUmVkIiwgTmVnTEZDPSJCbHVlIiksbmFtZT0iIikgKwogIGd1aWRlcyhjb2xvcj0ibm9uZSIpICsKICBnZ3RpdGxlKCJUcnVlIERBIikKCnN1YmNsX3Bsb3QgPC0gcGxfZGYgJT4lCiAgZ2dwbG90KGFlcyhYMSwgWDIsIGNvbG9yPXByZWREQV9zdWJjbHVzdGVycykpICsKICBnZW9tX3BvaW50KHNpemU9MC4xKSArCiAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE4KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKE5vdERBPSJncmV5IiwgUG9zTEZDPSJSZWQiLCBOZWdMRkM9IkJsdWUiKSxuYW1lPSIiKSArCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBjKHNpemU9MikpKSArCiAgZ2d0aXRsZSgiR0xNIG9uIHN1YmNsdXN0ZXJzIikKCmNsX3Bsb3QgPC0gcGxfZGYgJT4lCiAgZ2dwbG90KGFlcyhYMSwgWDIsIGNvbG9yPXByZWREQV9jZWxsdHlwZSkpICsKICBnZW9tX3BvaW50KHNpemU9MC4xKSArCiAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE4KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKE5vdERBPSJncmV5IiwgUG9zTEZDPSJSZWQiLCBOZWdMRkM9IkJsdWUiKSxuYW1lPSIiKSArCiAgZ3VpZGVzKGNvbG9yPSJub25lIikgKwogIGdndGl0bGUoIkdMTSBvbiBjbHVzdGVycyIpCgptaWxvX3BsIDwtIHBsX2RmICU+JQogIGdncGxvdChhZXMoWDEsIFgyLCBjb2xvcj1wcmVkREFfbWlsbykpICsKICBnZW9tX3BvaW50KHNpemU9MC4xKSArCiAgeGxhYigiVU1BUDEiKSArIHlsYWIoIlVNQVAyIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplPTE4KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKE5vdERBPSJncmV5IiwgUG9zTEZDPSJSZWQiLCBOZWdMRkM9IkJsdWUiKSwgbmFtZT0iIikgKwogIGd1aWRlcyhjb2xvcj0ibm9uZSIpICsKICBnZ3RpdGxlKCJNaWxvIikKCmZpZzIgPC0gdHJ1ZV9wbCArIG1pbG9fcGwgKyBjbF9wbG90ICsgc3ViY2xfcGxvdCArCiAgcGxvdF9sYXlvdXQobmNvbD0yLCBucm93PTIsIGd1aWRlcz0iY29sbGVjdCIpIApgYGAKCgpDb21wYXJlIHNpemUgb2Ygc3ViY2x1c3RlcnMgYW5kIHNpemUgb2YgbmVpZ2hib3VyaG9vZHMKCmBgYHtyfQpzaXplX2ZpZyA8LSAoZGF0YS5mcmFtZSh0YWJsZShlbWJyeW9fc2NlJHN1YmNsdXN0ZXIpKSAlPiUKICBnZ3Bsb3QoYWVzKEZyZXEpKSArIGdlb21faGlzdG9ncmFtKCkgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gMTYpICsKICAgYW5ub3RhdGUoInRleHQiLCBsYWJlbD1wYXN0ZTAoIk4gPSAiLCBsZW5ndGgodW5pcXVlKGVtYnJ5b19zY2Ukc3ViY2x1c3RlcikpKSwgeD03NTAsIHk9MjAsIHNpemU9NSkgKwogICB4bGFiKCJTdWJjbHVzdGVyIHNpemUiKSArCiAgeGxpbSgwLCAxMDAwKSkgLwoocGxvdE5ob29kU2l6ZUhpc3QobWlsb19yZXMkTWlsbykgKwogIHhsaW0oMCwgMTAwMCkgKwogICBhbm5vdGF0ZSgidGV4dCIsIGxhYmVsPXBhc3RlMCgiTiA9ICIsIG5jb2wobmhvb2RzKG1pbG9fcmVzJE1pbG8pKSksIHg9NzUwLCB5PTYwMCwgc2l6ZT01KSArCiAgIHhsYWIoIk1pbG8gbmVpZ2hib3VyaG9vZCBzaXplIikpCgpzaXplX2ZpZwpgYGAKYGBge3IsIGZpZy53aWR0aD0xNCwgZmlnLmhlaWdodD04fQooKCgoc3ViY2x1c3RlcnNfdW1hcCArIGdndGl0bGUoIlN1YmNsdXN0ZXJzIikpIC8gIHNpemVfZmlnKSArIHBsb3RfbGF5b3V0KG5jb2w9MSkpIHwKICAgZmlnMiApICsKICBwbG90X2xheW91dChuY29sPTIsIHdpZHRocz1jKDEsMikpICsKICBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICdBJykgKwogIGdnc2F2ZSgifi9tb3VudC9nZHJpdmUvbWlsby9GaWd1cmVzL1JlYnV0dGFsRmlnMV9taWNyb2NsdXN0ZXJzLnBuZyIsIHdpZHRoID0gMTQsIGhlaWdodCA9IDgpCmBgYAoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gIyBzdWJjbDJ0cnVlID0gZGF0YS5mcmFtZSh0cnVlREEgPSBlbWJyeW9fc2NlJHRydWVfbGFiZWxzLCBzdWJjbD1lbWJyeW9fc2NlJHN1YmNsdXN0ZXIpIC0tPgoKPCEtLSBjbHVzdC5kZiAlPiUgLS0+CjwhLS0gICBtdXRhdGUoc3ViY2xfc2l6ZSA9IHRhYmxlKGVtYnJ5b19zY2Ukc3ViY2x1c3RlcilbTG91dmFpbi5DbHVzdF0pICU+JSAtLT4KPCEtLSAgIHJlbmFtZShzdWJjbD1Mb3V2YWluLkNsdXN0KSAlPiUgLS0+CjwhLS0gICAjIGxlZnRfam9pbihzdWJjbDJ0cnVlKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKHN1YmNsX3NpemUsIC1sb2cxMChGRFIpKSkgKyBnZW9tX3BvaW50KCkgKyAtLT4KPCEtLSAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEpIC0tPgoKPCEtLSBtaWxvX3JlcyREQXJlcyAlPiUgLS0+CjwhLS0gICBtdXRhdGUobmhfc2l6ZSA9IGNvbFN1bXMobmhvb2RzKG1pbG9fcmVzJE1pbG8pKSkgJT4lIC0tPgo8IS0tICAgZ2dwbG90KGFlcyhuaF9zaXplLCAtbG9nMTAoU3BhdGlhbEZEUikpKSArIGdlb21fcG9pbnQoKSArIC0tPgo8IS0tICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSkgLS0+Cgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIHRhYmxlKG1pbG9fcmVzJE1pbG8kc3ludGhfbGFiZWxzKSAtLT4KPCEtLSB0YWJsZShtaWxvX3JlcyRNaWxvJHN5bnRoX3NhbXBsZXMpIC0tPgoKPCEtLSBuaF9jb3VudHMgPC0gbmhvb2RDb3VudHMobWlsb19yZXMkTWlsbykgLS0+Cgo8IS0tIG1lbHQoYXMubWF0cml4KG5oX2NvdW50cyksIHZhcm5hbWVzPWMoJ25oJywgInNhbXBsZSIpKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoY29uZGl0aW9uPXN0cl9yZW1vdmUoc2FtcGxlLCAiX1IuKyIpKSAlPiUgLS0+CjwhLS0gICBncm91cF9ieShzYW1wbGUpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShNX3M9c3VtKHZhbHVlKSkgJT4lIC0tPgo8IS0tICAgZ2dwbG90KGFlcyh2YWx1ZSwgZ3JvdXA9c2FtcGxlLCBjb2xvcj1jb25kaXRpb24pKSArIGdlb21fZGVuc2l0eSgpIC0tPgoKPCEtLSBtZWx0KGFzLm1hdHJpeChsb3V2YWluLmNvdW50KSwgdmFybmFtZXM9YygnbmgnLCAic2FtcGxlIikpICU+JSAtLT4KPCEtLSAgIG11dGF0ZShjb25kaXRpb249c3RyX3JlbW92ZShzYW1wbGUsICJfUi4rIikpICU+JSAtLT4KPCEtLSAgIGdyb3VwX2J5KHNhbXBsZSkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKE1fcz1zdW0odmFsdWUpKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKHZhbHVlL01fcywgZ3JvdXA9c2FtcGxlLCBjb2xvcj1jb25kaXRpb24pKSArIGdlb21fZGVuc2l0eSgpIC0tPgoKPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gbWVsdChhcy5tYXRyaXgobG91dmFpbi5jb3VudCksIHZhcm5hbWVzPWMoJ25oJywgInNhbXBsZSIpKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoY29uZGl0aW9uPXN0cl9yZW1vdmUoc2FtcGxlLCAiX1IuKyIpKSAlPiUgLS0+CjwhLS0gICBncm91cF9ieShuaCkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKG5oX3NpemU9c3VtKHZhbHVlKSkgJT4lIC0tPgo8IS0tICAgdW5ncm91cCgpICU+JSAtLT4KPCEtLSAgIGdyb3VwX2J5KGNvbmRpdGlvbiwgbmgpICU+JSAtLT4KPCEtLSAgIHN1bW1hcmlzZSh2YWx1ZT1tZWFuKHZhbHVlKSwgbmhfc2l6ZT1tZWFuKG5oX3NpemUpKSAlPiUgLS0+CjwhLS0gICBwaXZvdF93aWRlcihpZF9jb2xzPWMobmgsIG5oX3NpemUpLCBuYW1lc19mcm9tPSJjb25kaXRpb24iLCB2YWx1ZXNfZnJvbT0ndmFsdWUnKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKENvbmRpdGlvbjEsIENvbmRpdGlvbjIsIGNvbG9yPW5oX3NpemUpKSArIC0tPgo8IS0tICAgZ2VvbV9wb2ludCgpICsgLS0+CjwhLS0gICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikgKyAtLT4KPCEtLSAgIGdlb21fYWJsaW5lKGNvbG9yPSJyZWQiKSAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIERvd25zYW1wbGUgQ29uZGl0aW9uMSAtLT4KPCEtLSBgYGB7cn0gLS0+CjwhLS0gTSA8LSB0YWJsZShlbWJyeW9fc2NlJHN5bnRoX3NhbXBsZXMpIC0tPgo8IS0tIGNlbGxfaWRzX3MgPC0gc3BsaXQoY29sbmFtZXMoZW1icnlvX3NjZSksIGVtYnJ5b19zY2Ukc3ludGhfc2FtcGxlcykgLS0+CjwhLS0gY2VsbF9pZHNfcyRDb25kaXRpb24xX1IxIDwtIHNhbXBsZShjZWxsX2lkc19zJENvbmRpdGlvbjFfUjEsIGxlbmd0aChjZWxsX2lkc19zJENvbmRpdGlvbjJfUjEpKSAtLT4KPCEtLSBjZWxsX2lkc19zJENvbmRpdGlvbjFfUjIgPC0gc2FtcGxlKGNlbGxfaWRzX3MkQ29uZGl0aW9uMV9SMiwgbGVuZ3RoKGNlbGxfaWRzX3MkQ29uZGl0aW9uMl9SMikpIC0tPgo8IS0tIGNlbGxfaWRzX3MkQ29uZGl0aW9uMV9SMyA8LSBzYW1wbGUoY2VsbF9pZHNfcyRDb25kaXRpb24xX1IzLCBsZW5ndGgoY2VsbF9pZHNfcyRDb25kaXRpb24yX1IzKSkgLS0+Cgo8IS0tIHNjZTIgPC0gZW1icnlvX3NjZVssdW5saXN0KGNlbGxfaWRzX3MpXSAtLT4KCjwhLS0gbWlsbzIgPC0gTWlsbyhzY2UyKSAtLT4KPCEtLSBtaWxvMiA8LSBidWlsZEdyYXBoKG1pbG8yLCByZWR1Y2VkLmRpbSA9ICJwY2EuY29ycmVjdGVkIiwgaz01MCwgZD0zMCkgLS0+CjwhLS0gbWlsbzIgPC0gbWFrZU5ob29kcyhtaWxvMikgLS0+CjwhLS0gbWlsbzIgPC0gbWlsb1I6OmNvdW50Q2VsbHMobWlsbzIsIG1ldGEuZGF0YSA9IGRhdGEuZnJhbWUoY29sRGF0YShtaWxvMikpLCBzYW1wbGVzID0gInN5bnRoX3NhbXBsZXMiKSAtLT4KCjwhLS0gbmhfY291bnRzIDwtIG5ob29kQ291bnRzKG1pbG8yKSAtLT4KPCEtLSBtZWx0KGFzLm1hdHJpeChuaF9jb3VudHMpLCB2YXJuYW1lcz1jKCduaCcsICJzYW1wbGUiKSkgJT4lIC0tPgo8IS0tICAgbXV0YXRlKGNvbmRpdGlvbj1zdHJfcmVtb3ZlKHNhbXBsZSwgIl9SLisiKSkgJT4lIC0tPgo8IS0tICAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgLS0+CjwhLS0gICBtdXRhdGUoTV9zPXN1bSh2YWx1ZSkpICU+JSAtLT4KPCEtLSAgIGdncGxvdChhZXModmFsdWUsIGdyb3VwPXNhbXBsZSwgY29sb3I9Y29uZGl0aW9uKSkgKyBnZW9tX2RlbnNpdHkoKSAtLT4KPCEtLSBgYGAgLS0+CjwhLS0gYGBge3J9IC0tPgo8IS0tIGRlc2lnbl9kZiA8LSBhcy50aWJibGUoY29sRGF0YShzY2UyKVtjKHNhbXBsZV9jb2wsIGNvbmRpdGlvbl9jb2wpXSkgJT4lIC0tPgo8IS0tICAgICBkaXN0aW5jdCgpICU+JSAtLT4KPCEtLSAgICAgY29sdW1uX3RvX3Jvd25hbWVzKHNhbXBsZV9jb2wpIC0tPgoKPCEtLSBtaWxvMiA8LSBjYWxjTmhvb2REaXN0YW5jZShtaWxvMiwgZD0zMCwgcmVkdWNlZC5kaW0gPSAicGNhLmNvcnJlY3RlZCIpIC0tPgo8IS0tIERBX3Jlc3VsdHMgPC0gdGVzdE5ob29kcyhtaWxvMiwgZGVzaWduID0gfiBzeW50aF9sYWJlbHMsICAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduLmRmID0gZGVzaWduX2RmW2NvbG5hbWVzKG5ob29kQ291bnRzKG1pbG8yKSksICwgZHJvcD1GQUxTRV0pIC0tPgo8IS0tIGRhIC0tPgo8IS0tIGBgYCAtLT4KCgoKCgo=